// Copyright (c) 2012, 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. using System; using System.Collections; using System.Management; using System.DirectoryServices; using System.DirectoryServices.ActiveDirectory; using System.Collections.Generic; using System.Text; using System.IO; using WebsitePanel.Providers.HostedSolution; using WebsitePanel.Providers.OS; using WebsitePanel.Providers.ResultObjects; using WebsitePanel.Providers.Utils; using WebsitePanel.Providers.Web.Handlers; using WebsitePanel.Providers.Web.HttpRedirect; using WebsitePanel.Providers.Web.Iis.Authentication; using WebsitePanel.Providers.Web.Iis.ClassicAsp; using WebsitePanel.Providers.Web.Iis.DefaultDocuments; using WebsitePanel.Providers.Web.Iis.DirectoryBrowse; using WebsitePanel.Providers.Web.Iis.WebObjects; using WebsitePanel.Providers.Web.Iis.Extensions; using WebsitePanel.Providers.Web.MimeTypes; using WebsitePanel.Providers.Web.Iis.Utility; using Microsoft.Web.Administration; using Microsoft.Web.Management.Server; using WebsitePanel.Providers.Utils.LogParser; using Microsoft.Win32; using WebsitePanel.Providers.Common; using System.Collections.Specialized; using WebsitePanel.Providers.Web.WebObjects; using WebsitePanel.Providers.Web.Iis.Common; using WebsitePanel.Providers.Web.Iis; using Ionic.Zip; using WebsitePanel.Providers.WebAppGallery; using WebsitePanel.Server.Utils; using WebsitePanel.Providers.Web.Delegation; namespace WebsitePanel.Providers.Web { internal abstract class Constants { public const string CachingSection = "system.webServer/caching"; public const string DefaultDocumentsSection = "system.webServer/defaultDocument"; public const string DirectoryBrowseSection = "system.webServer/directoryBrowse"; public const string FactCgiSection = "system.webServer/fastCgi"; public const string HandlersSection = "system.webServer/handlers"; public const string HttpErrorsSection = "system.webServer/httpErrors"; public const string HttpProtocolSection = "system.webServer/httpProtocol"; public const string HttpRedirectSection = "system.webServer/httpRedirect"; public const string AnonymousAuthenticationSection = "system.webServer/security/authentication/anonymousAuthentication"; public const string BasicAuthenticationSection = "system.webServer/security/authentication/basicAuthentication"; public const string WindowsAuthenticationSection = "system.webServer/security/authentication/windowsAuthentication"; public const string StaticContentSection = "system.webServer/staticContent"; public const string ModulesSection = "system.webServer/modules"; public const string IsapiCgiRestrictionSection = "system.webServer/security/isapiCgiRestriction"; public const string APP_POOL_NAME_FORMAT_STRING = "#SITE-NAME# #IIS7-ASPNET-VERSION# (#PIPELINE-MODE#)"; public const string AspNet11Pool = "AspNet11Pool"; public const string ClassicAspNet20Pool = "ClassicAspNet20Pool"; public const string IntegratedAspNet20Pool = "IntegratedAspNet20Pool"; public const string ClassicAspNet40Pool = "ClassicAspNet40Pool"; public const string IntegratedAspNet40Pool = "IntegratedAspNet40Pool"; public const string AspPathSetting = "AspPath"; public const string AspNet11PathSetting = "AspNet11Path"; public const string AspNet20PathSetting = "AspNet20Path"; public const string AspNet20x64PathSetting = "AspNet20x64Path"; public const string AspNet40PathSetting = "AspNet40Path"; public const string AspNet40x64PathSetting = "AspNet40x64Path"; public const string WEBSITEPANEL_IISMODULES = "WebsitePanel.IIsModules"; public const string HeliconApeModule = "Helicon Ape"; public const string HeliconApeHandlerPath = "*.apehandler"; public const string IsapiModule = "IsapiModule"; public const string FastCgiModule = "FastCgiModule"; public const string CgiModule = "CgiModule"; internal abstract class PhpMode { public const string FastCGI = "FastCGI"; public const string CGI = "CGI"; public const string ISAPI = "ISAPI"; } internal abstract class HandlerAlias { public const string CLASSIC_ASP = "ASPClassic (*{0})"; public const string PHP_FASTCGI = "PHP via FastCGI (*{0})"; public const string PHP_CGI = "PHP via CGI (*{0})"; public const string PERL_ISAPI = "Perl via ISAPI (*{0})"; public const string PHP_ISAPI = "PHP via ISAPI (*{0})"; public const string COLDFUSION = "ColdFusion (*{0})"; } public static bool X64Environment { get { return (IntPtr.Size == 8); } } } public class WebAppPool { public static readonly Dictionary AspNetVersions = new Dictionary { { SiteAppPoolMode.dotNetFramework1, "v1.1" }, { SiteAppPoolMode.dotNetFramework2, "v2.0" }, { SiteAppPoolMode.dotNetFramework4, "v4.0" } }; public string AspNetInstalled { get; set; } public SiteAppPoolMode Mode { get; set; } public string Name { get; set; } } public class WebAppPoolHelper { private List supportedAppPools; public List SupportedAppPools { get { return supportedAppPools; } } public static Dictionary SupportedAppPoolModes = new Dictionary { { "1", SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.Classic }, { "2", SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Classic }, { "2I", SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Integrated }, { "4", SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Classic }, { "4I", SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Integrated } }; // public WebAppPoolHelper(ServiceProviderSettings s) { SetupSupportedAppPools(s); } // public SiteAppPoolMode dotNetVersion(SiteAppPoolMode m) { return m & (SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.dotNetFramework4); } // public SiteAppPoolMode pipeline(SiteAppPoolMode m) { return m & (SiteAppPoolMode.Classic | SiteAppPoolMode.Integrated); } // public SiteAppPoolMode isolation(SiteAppPoolMode m) { return m & (SiteAppPoolMode.Shared | SiteAppPoolMode.Dedicated); } // public string aspnet_runtime(SiteAppPoolMode m) { return WebAppPool.AspNetVersions[dotNetVersion(m)]; } // public ManagedPipelineMode runtime_pipeline(SiteAppPoolMode m) { return (pipeline(m) == SiteAppPoolMode.Classic) ? ManagedPipelineMode.Classic : ManagedPipelineMode.Integrated; } // public bool is_shared_pool(string poolName) { return Array.Exists(supportedAppPools.ToArray(), x => x.Name.Equals(poolName) && isolation(x.Mode) == SiteAppPoolMode.Shared); } // public WebAppPool match_webapp_pool(WebVirtualDirectory vdir) { // Detect isolation mode SiteAppPoolMode sisMode = is_shared_pool(vdir.ApplicationPool) ? SiteAppPoolMode.Shared : SiteAppPoolMode.Dedicated; // Match proper app pool return Array.Find(SupportedAppPools.ToArray(), x => x.AspNetInstalled.Equals(vdir.AspNetInstalled) && isolation(x.Mode) == sisMode); } // private void SetupSupportedAppPools(ServiceProviderSettings settings) { supportedAppPools = new List(); #region Populate Shared Application Pools // ASP.NET 1.1 if (!String.IsNullOrEmpty(settings[Constants.AspNet11Pool])) { supportedAppPools.Add(new WebAppPool { AspNetInstalled = "1", Mode = SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.Classic | SiteAppPoolMode.Shared, Name = settings[Constants.AspNet11Pool].Trim() }); } // ASP.NET 2.0 (Classic pipeline) if (!String.IsNullOrEmpty(settings[Constants.ClassicAspNet20Pool])) { supportedAppPools.Add(new WebAppPool { AspNetInstalled = "2", Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Classic | SiteAppPoolMode.Shared, Name = settings[Constants.ClassicAspNet20Pool].Trim() }); } // ASP.NET 2.0 (Integrated pipeline) if (!String.IsNullOrEmpty(settings[Constants.IntegratedAspNet20Pool])) { supportedAppPools.Add(new WebAppPool { AspNetInstalled = "2I", Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Shared, Name = settings[Constants.IntegratedAspNet20Pool].Trim() }); } // ASP.NET 4.0 (Classic pipeline) if (!String.IsNullOrEmpty(settings[Constants.ClassicAspNet40Pool])) { supportedAppPools.Add(new WebAppPool { AspNetInstalled = "4", Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Classic | SiteAppPoolMode.Shared, Name = settings[Constants.ClassicAspNet40Pool].Trim() }); } // ASP.NET 4.0 (Integrated pipeline) if (!String.IsNullOrEmpty(settings[Constants.IntegratedAspNet40Pool])) { supportedAppPools.Add(new WebAppPool { AspNetInstalled = "4I", Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Shared, Name = settings[Constants.IntegratedAspNet40Pool].Trim() }); } #endregion #region Populate Dedicated Application Pools // ASP.NET 1.1 supportedAppPools.Add(new WebAppPool { AspNetInstalled = "1", Mode = SiteAppPoolMode.dotNetFramework1 | SiteAppPoolMode.Classic | SiteAppPoolMode.Dedicated, Name = Constants.APP_POOL_NAME_FORMAT_STRING }); // ASP.NET 2.0 (Classic pipeline) supportedAppPools.Add(new WebAppPool { AspNetInstalled = "2", Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Classic | SiteAppPoolMode.Dedicated, Name = Constants.APP_POOL_NAME_FORMAT_STRING }); // ASP.NET 2.0 (Integrated pipeline) supportedAppPools.Add(new WebAppPool { AspNetInstalled = "2I", Mode = SiteAppPoolMode.dotNetFramework2 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Dedicated, Name = Constants.APP_POOL_NAME_FORMAT_STRING }); // ASP.NET 4.0 (Classic pipeline) supportedAppPools.Add(new WebAppPool { AspNetInstalled = "4", Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Classic | SiteAppPoolMode.Dedicated, Name = Constants.APP_POOL_NAME_FORMAT_STRING }); // ASP.NET 4.0 (Integrated pipeline) supportedAppPools.Add(new WebAppPool { AspNetInstalled = "4I", Mode = SiteAppPoolMode.dotNetFramework4 | SiteAppPoolMode.Integrated | SiteAppPoolMode.Dedicated, Name = Constants.APP_POOL_NAME_FORMAT_STRING }); #endregion // Make some corrections for frameworks with the version number greater or less than 2.0 ... #region No ASP.NET 1.1 has been found - so remove extra pools if (String.IsNullOrEmpty(settings[Constants.AspNet11PathSetting])) supportedAppPools.RemoveAll(x => dotNetVersion(x.Mode) == SiteAppPoolMode.dotNetFramework1); #endregion #region No ASP.NET 4.0 has been found - so remove extra pools var aspNet40PathSetting = (Constants.X64Environment) ? Constants.AspNet40x64PathSetting : Constants.AspNet40PathSetting; // if (String.IsNullOrEmpty(settings[aspNet40PathSetting])) supportedAppPools.RemoveAll(x => dotNetVersion(x.Mode) == SiteAppPoolMode.dotNetFramework4); #endregion } } public class WebManagementServiceSettings { public string Port { get; set; } public string NETBIOS { get; set; } public string ServiceUrl { get; set; } public int RequiresWindowsCredentials { get; set; } } public class IIs70 : IIs60, IWebServer { private WebObjectsModuleService webObjectsSvc; private DirectoryBrowseModuleService dirBrowseSvc; private AnonymAuthModuleService anonymAuthSvc; private WindowsAuthModuleService winAuthSvc; private BasicAuthModuleService basicAuthSvc; private DefaultDocsModuleService defaultDocSvc; private CustomHttpErrorsModuleService customErrorsSvc; private CustomHttpHeadersModuleService customHeadersSvc; private ClassicAspModuleService classicAspSvc; private MimeTypesModuleService mimeTypesSvc; private ExtensionsModuleService extensionsSvc; private HandlersModuleService handlersSvc; private HttpRedirectModuleService httpRedirectSvc; // #region Constants public const string IIS_IUSRS_GROUP = "IIS_IUSRS"; // public const string FPSE2002_OWSADM_PATH_x86 = @"%CommonProgramFiles%\Microsoft Shared\Web Server Extensions\50\bin\owsadm.exe"; public const string FPSE2002_OWSADM_PATH_x64 = @"%CommonProgramFiles(x86)%\Microsoft Shared\Web Server Extensions\50\bin\owsadm.exe"; // public const string FRONTPAGE_2002_REGLOC_x86 = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\5.0"; public const string FRONTPAGE_2002_REGLOC_x64 = @"SOFTWARE\Wow6432Node\Microsoft\Shared Tools\Web Server Extensions\5.0"; // public const string FRONTPAGE_ALLPORTS_REGLOC_x86 = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\All Ports\"; public const string FRONTPAGE_ALLPORTS_REGLOC_x64 = @"SOFTWARE\Wow6432Node\Microsoft\Shared Tools\Web Server Extensions\All Ports\"; // public const string FRONTPAGE_PORT_REGLOC_x86 = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\Ports\"; public const string FRONTPAGE_PORT_REGLOC_x64 = @"SOFTWARE\Wow6432Node\Microsoft\Shared Tools\Web Server Extensions\Ports\"; private string[] INSTALL_SECTIONS_ALLOWED = new string[] { Constants.CachingSection, Constants.DefaultDocumentsSection, Constants.DirectoryBrowseSection, Constants.FactCgiSection, Constants.HandlersSection, Constants.HttpErrorsSection, Constants.HttpProtocolSection, Constants.HttpRedirectSection, Constants.AnonymousAuthenticationSection, Constants.BasicAuthenticationSection, Constants.WindowsAuthenticationSection, Constants.StaticContentSection }; #endregion #region Helper Properties protected string FPSE2002_OWSADM_PATH { get { if (Constants.X64Environment) return FPSE2002_OWSADM_PATH_x64; else return FPSE2002_OWSADM_PATH_x86; } } new protected string FRONTPAGE_2002_REGLOC { get { if (Constants.X64Environment) return FRONTPAGE_2002_REGLOC_x64; else return FRONTPAGE_2002_REGLOC_x86; } } new protected string FRONTPAGE_ALLPORTS_REGLOC { get { if (Constants.X64Environment) return FRONTPAGE_ALLPORTS_REGLOC_x64; else return FRONTPAGE_ALLPORTS_REGLOC_x86; } } new protected string FRONTPAGE_PORT_REGLOC { get { if (Constants.X64Environment) return FRONTPAGE_PORT_REGLOC_x64; else return FRONTPAGE_PORT_REGLOC_x86; } } #endregion #region Provider Properties public bool Enable32BitAppOnWin64 { get { return ProviderSettings["AspNetBitnessMode"] == "32"; } } /// /// Gets shared iisAppObject pool name (Classic Managed Pipeline) /// public string ClassicAspNet20Pool { get { return ProviderSettings["ClassicAspNet20Pool"]; } } /// /// Gets shared iisAppObject pool name (Integrated Managed Pipeline) /// public string IntegratedAspNet20Pool { get { return ProviderSettings["IntegratedAspNet20Pool"]; } } /// /// Gets shared iisAppObject pool name (Classic Managed Pipeline) /// public string ClassicAspNet40Pool { get { return ProviderSettings["ClassicAspNet40Pool"]; } } /// /// Gets shared iisAppObject pool name (Integrated Managed Pipeline) /// public string IntegratedAspNet40Pool { get { return ProviderSettings["IntegratedAspNet40Pool"]; } } public string PhpMode { get { return ProviderSettings["PhpMode"]; } } public string PhpExecutablePath { get { return FileUtils.EvaluateSystemVariables(ProviderSettings["PhpPath"]); } } public string SecureFoldersModuleAssembly { get { return ProviderSettings["SecureFoldersModuleAssembly"]; } } protected override string ProtectedAccessFile { get { return ".htaccess"; } } protected override string ProtectedFoldersFile { get { return ".htfolders"; } } #endregion public IIs70() { if (IsIISInstalled()) { // New implementation avoiding locks and other sync issues winAuthSvc = new WindowsAuthModuleService(); anonymAuthSvc = new AnonymAuthModuleService(); basicAuthSvc = new BasicAuthModuleService(); defaultDocSvc = new DefaultDocsModuleService(); classicAspSvc = new ClassicAspModuleService(); httpRedirectSvc = new HttpRedirectModuleService(); extensionsSvc = new ExtensionsModuleService(); customErrorsSvc = new CustomHttpErrorsModuleService(); customHeadersSvc = new CustomHttpHeadersModuleService(); webObjectsSvc = new WebObjectsModuleService(); dirBrowseSvc = new DirectoryBrowseModuleService(); mimeTypesSvc = new MimeTypesModuleService(); handlersSvc = new HandlersModuleService(); } } #region Helper methods private void CreateWebSiteAnonymousAccount(WebSite site) { // anonymous user groups List webGroups = new List(); webGroups.Add(WebGroupName); // create web site anonymous account SystemUser user = new SystemUser(); user.Name = GetNonQualifiedAccountName(site.AnonymousUsername); user.FullName = GetNonQualifiedAccountName(site.AnonymousUsername); // Fix. Import web site that runs under NETWORK_SERVICE identity fails. // WebsitePanel cannot create anonymous account. /*if (!user.Name.Contains(site.Name.Replace(".", ""))) { user.Name = user.FullName = site.Name.Replace(".", "") + "_web"; }*/ //check is user name less than 20 symbols (Windows name length restriction) if (user.Name.Length > 20) { int separatorPlace = user.Name.IndexOf("_"); user.Name = user.Name.Remove(separatorPlace - (user.Name.Length - 20), user.Name.Length - 20); } site.AnonymousUsername = user.Name; user.Description = "WebsitePanel System Account"; user.MemberOf = webGroups.ToArray(); //set new password for created Anonymous Account if (String.IsNullOrEmpty(site.AnonymousUserPassword)) { site.AnonymousUserPassword = Guid.NewGuid().ToString(); } user.Password = site.AnonymousUserPassword; user.PasswordCantChange = true; user.PasswordNeverExpires = true; user.AccountDisabled = false; user.System = true; // create in the system try { SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU); } catch (Exception ex) { // the possible reason the account already exists // check this if (SecurityUtils.UserExists(user.Name, ServerSettings, UsersOU)) { // yes // try to give it original name for (int i = 2; i < 99; i++) { string username = user.Name + i.ToString(); if (!SecurityUtils.UserExists(username, ServerSettings, UsersOU)) { user.Name = username; site.AnonymousUsername = username; // try to create again SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU); break; } } } else { throw ex; } } } private void FillVirtualDirectoryFromIISObject(ServerManager srvman, WebVirtualDirectory virtualDir) { // Set physical path. virtualDir.ContentPath = webObjectsSvc.GetPhysicalPath(srvman, virtualDir); // load iisDirObject browse PropertyBag bag = dirBrowseSvc.GetDirectoryBrowseSettings(srvman, virtualDir.FullQualifiedPath); virtualDir.EnableDirectoryBrowsing = (bool)bag[DirectoryBrowseGlobals.Enabled]; // load anonym auth bag = anonymAuthSvc.GetAuthenticationSettings(srvman, virtualDir.FullQualifiedPath); virtualDir.AnonymousUsername = (string)bag[AuthenticationGlobals.AnonymousAuthenticationUserName]; virtualDir.AnonymousUserPassword = (string)bag[AuthenticationGlobals.AnonymousAuthenticationPassword]; virtualDir.EnableAnonymousAccess = (bool)bag[AuthenticationGlobals.Enabled]; // load windows auth bag = winAuthSvc.GetAuthenticationSettings(srvman, virtualDir.FullQualifiedPath); virtualDir.EnableWindowsAuthentication = (bool)bag[AuthenticationGlobals.Enabled]; // load basic auth basicAuthSvc.GetAuthenticationSettings(srvman, virtualDir); // load default docs virtualDir.DefaultDocs = defaultDocSvc.GetDefaultDocumentSettings(srvman, virtualDir.FullQualifiedPath); // load classic asp bag = classicAspSvc.GetClassicAspSettings(srvman, virtualDir.FullQualifiedPath); virtualDir.EnableParentPaths = (bool)bag[ClassicAspGlobals.EnableParentPaths]; // virtualDir.IIs7 = true; } private void FillIISObjectFromVirtualDirectory(WebVirtualDirectory virtualDir) { dirBrowseSvc.SetDirectoryBrowseEnabled(virtualDir.FullQualifiedPath, virtualDir.EnableDirectoryBrowsing); // SetAnonymousAuthentication(virtualDir); // winAuthSvc.SetEnabled(virtualDir.FullQualifiedPath, virtualDir.EnableWindowsAuthentication); // basicAuthSvc.SetAuthenticationSettings(virtualDir); // defaultDocSvc.SetDefaultDocumentSettings(virtualDir.FullQualifiedPath, virtualDir.DefaultDocs); // classicAspSvc.SetClassicAspSettings(virtualDir); } private void FillVirtualDirectoryRestFromIISObject(ServerManager srvman, WebVirtualDirectory virtualDir) { // HTTP REDIRECT httpRedirectSvc.GetHttpRedirectSettings(srvman, virtualDir); // HTTP HEADERS customHeadersSvc.GetCustomHttpHeaders(srvman, virtualDir); // HTTP ERRORS customErrorsSvc.GetCustomErrors(srvman, virtualDir); // MIME MAPPINGS mimeTypesSvc.GetMimeMaps(srvman, virtualDir); // SCRIPT MAPS // Load installed script maps. virtualDir.AspInstalled = false; // not installed virtualDir.PhpInstalled = ""; // none virtualDir.PerlInstalled = false; // not installed virtualDir.PythonInstalled = false; // not installed virtualDir.ColdFusionInstalled = false; // not installed // var config = srvman.GetWebConfiguration(virtualDir.FullQualifiedPath); var handlersSection = config.GetSection(Constants.HandlersSection); // Loop through available maps and fill installed processors foreach (ConfigurationElement action in handlersSection.GetCollection()) { // Extract and evaluate scripting processor path string processor = FileUtils.EvaluateSystemVariables( Convert.ToString(action.GetAttributeValue("scriptProcessor"))); // string actionName = Convert.ToString(action.GetAttributeValue("name")); // Detect whether ASP scripting is enabled if (!String.IsNullOrEmpty(AspPath) && String.Equals(AspPath, processor, StringComparison.InvariantCultureIgnoreCase)) virtualDir.AspInstalled = true; // Detect whether PHP 5 scripting is enabled if (!String.IsNullOrEmpty(PhpExecutablePath) && String.Equals(PhpExecutablePath, processor, StringComparison.InvariantCultureIgnoreCase)) virtualDir.PhpInstalled = PHP_5; // Detect whether PHP 4 scripting is enabled if (!String.IsNullOrEmpty(Php4Path) && String.Equals(Php4Path, processor, StringComparison.InvariantCultureIgnoreCase)) virtualDir.PhpInstalled = PHP_4; // Detect whether ColdFusion scripting is enabled if (!String.IsNullOrEmpty(ColdFusionPath) && String.Compare(ColdFusionPath, processor, true) == 0 && actionName.Contains(".cfm")) virtualDir.ColdFusionInstalled = true; // Detect whether Perl scripting is enabled if (!String.IsNullOrEmpty(PerlPath) && String.Equals(PerlPath, processor, StringComparison.InvariantCultureIgnoreCase)) virtualDir.PerlInstalled = true; } // string fqPath = virtualDir.FullQualifiedPath; if (!fqPath.EndsWith(@"/")) fqPath += "/"; // fqPath += CGI_BIN_FOLDER; // HandlerAccessPolicy policy = handlersSvc.GetHandlersAccessPolicy(srvman, fqPath); virtualDir.CgiBinInstalled = (policy & HandlerAccessPolicy.Execute) > 0; // ASP.NET FillAspNetSettingsFromIISObject(srvman, virtualDir); } private void FillAspNetSettingsFromIISObject(ServerManager srvman, WebVirtualDirectory vdir) { // Read ASP.NET settings if (String.IsNullOrEmpty(vdir.ApplicationPool)) return; // try { var appool = srvman.ApplicationPools[vdir.ApplicationPool]; // var aphl = new WebAppPoolHelper(ProviderSettings); // ASP.NET 2.0 pipeline is supposed by default var dotNetVersion = SiteAppPoolMode.dotNetFramework2; // #region Iterate over managed runtime keys of the helper class to properly evaluate ASP.NET version installed foreach (var k in WebAppPool.AspNetVersions) { if (k.Value.Equals(appool.ManagedRuntimeVersion)) { dotNetVersion = k.Key; break; } } #endregion // Detect pipeline mode being used if (appool.ManagedPipelineMode == ManagedPipelineMode.Classic) dotNetVersion |= SiteAppPoolMode.Classic; else dotNetVersion |= SiteAppPoolMode.Integrated; // var aspNetVersion = String.Empty; #region Iterate over supported ASP.NET versions based on result of the previous runtime version assesement foreach (var item in WebAppPoolHelper.SupportedAppPoolModes) { if (item.Value == dotNetVersion) { // Obtain ASP.NET version installed aspNetVersion = item.Key; // break; } } #endregion // Assign the result of assesement vdir.AspNetInstalled = aspNetVersion; } catch (Exception ex) { Log.WriteError(String.Format("Failed to read ASP.NET settings from {0}.", vdir.Name), ex); // Re-throw throw (ex); } } private void DeleteDedicatedPoolsAllocated(string siteName) { try { WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings); // var dedicatedPools = Array.FindAll(aphl.SupportedAppPools.ToArray(), x => aphl.isolation(x.Mode) == SiteAppPoolMode.Dedicated); // cleanup app pools using (var srvman = webObjectsSvc.GetServerManager()) { foreach (var item in dedicatedPools) { string poolName = WSHelper.InferAppPoolName(item.Name, siteName, item.Mode); // ApplicationPool pool = srvman.ApplicationPools[poolName]; if (pool == null) continue; // srvman.ApplicationPools.Remove(pool); } // save changes srvman.CommitChanges(); } } catch (Exception ex) { Log.WriteError(ex); throw (ex); } } private void FillIISObjectFromVirtualDirectoryRest(WebVirtualDirectory virtualDir) { // TO-DO: HTTP REDIRECT httpRedirectSvc.SetHttpRedirectSettings(virtualDir); // TO-DO: HTTP HEADERS customHeadersSvc.SetCustomHttpHeaders(virtualDir); // TO-DO: HTTP ERRORS customErrorsSvc.SetCustomErrors(virtualDir); // TO-DO: MIME MAPPINGS mimeTypesSvc.SetMimeMaps(virtualDir); // Revert script mappings to the parent to simplify script mappings cleanup //handlersSvc.InheritScriptMapsFromParent(virtualDir.FullQualifiedPath); // TO-DO: SCRIPT MAPS #region ASP script mappings if (!String.IsNullOrEmpty(AspPath) && File.Exists(AspPath)) { // Classic ASP if (virtualDir.AspInstalled) { handlersSvc.AddScriptMaps(virtualDir, ASP_EXTENSIONS, AspPath, Constants.HandlerAlias.CLASSIC_ASP, Constants.IsapiModule); } else { handlersSvc.RemoveScriptMaps(virtualDir, ASP_EXTENSIONS, AspPath); } } #endregion #region PHP 5 script mappings if (!String.IsNullOrEmpty(PhpExecutablePath) && File.Exists(PhpExecutablePath)) { if (virtualDir.PhpInstalled == PHP_5) { switch (PhpMode) { case Constants.PhpMode.FastCGI: handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath, Constants.HandlerAlias.PHP_FASTCGI, Constants.FastCgiModule); break; case Constants.PhpMode.CGI: handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath, Constants.HandlerAlias.PHP_CGI, Constants.CgiModule); break; case Constants.PhpMode.ISAPI: handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath, Constants.HandlerAlias.PHP_ISAPI, Constants.IsapiModule); break; } } else { handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, PhpExecutablePath); } } // #endregion #region PHP 4 script mappings (IsapiModule only) if (!String.IsNullOrEmpty(Php4Path) && File.Exists(Php4Path)) { if (virtualDir.PhpInstalled == PHP_4) { handlersSvc.AddScriptMaps(virtualDir, PHP_EXTENSIONS, Php4Path, Constants.HandlerAlias.PHP_ISAPI, Constants.IsapiModule); } else { handlersSvc.RemoveScriptMaps(virtualDir, PHP_EXTENSIONS, Php4Path); } } // #endregion #region PERL scrit mappings // if (!String.IsNullOrEmpty(PerlPath) && File.Exists(PerlPath)) { // Start from building Perl-specific CGI-executable definition // IsapiModule if (virtualDir.PerlInstalled) { // Perl works only in 32-bit mode on x64 environment webObjectsSvc.ForceEnableAppPoolWow6432Mode(virtualDir.ApplicationPool); // handlersSvc.AddScriptMaps(virtualDir, PERL_EXTENSIONS, PerlPath, Constants.HandlerAlias.PERL_ISAPI, Constants.IsapiModule); } else { handlersSvc.RemoveScriptMaps(virtualDir, PERL_EXTENSIONS, PerlPath); } } // #endregion #region ColdFusion script mappings //ColdFusion code if (virtualDir.ColdFusionInstalled) { handlersSvc.AddScriptMaps(virtualDir, COLDFUSION_EXTENSIONS, ColdFusionPath, Constants.HandlerAlias.COLDFUSION, Constants.IsapiModule); } else { handlersSvc.RemoveScriptMaps(virtualDir, COLDFUSION_EXTENSIONS, ColdFusionPath); } #endregion // TO-DO: REST } /// /// Update CGI-Bin /// /// Already installed scrip maps. /// Extensions to check. /// Extensions processor. private void UpdateCgiBinFolder(WebVirtualDirectory virtualDir) { // string fqPath = virtualDir.FullQualifiedPath; if (!fqPath.EndsWith(@"/")) fqPath += "/"; // fqPath += CGI_BIN_FOLDER; string cgiBinPath = Path.Combine(virtualDir.ContentPath, CGI_BIN_FOLDER); using (ServerManager srvman = webObjectsSvc.GetServerManager()) { // HandlerAccessPolicy policy = handlersSvc.GetHandlersAccessPolicy(srvman, fqPath); policy &= ~HandlerAccessPolicy.Execute; // if (virtualDir.CgiBinInstalled) { // create folder if not exists if (!FileUtils.DirectoryExists(cgiBinPath)) FileUtils.CreateDirectory(cgiBinPath); // policy |= HandlerAccessPolicy.Execute; } // if (FileUtils.DirectoryExists(cgiBinPath)) handlersSvc.SetHandlersAccessPolicy(srvman, fqPath, policy); // save srvman.CommitChanges(); } } /// /// Sets anonymous authentication for the virtual iisDirObject /// /// private void SetAnonymousAuthentication(WebVirtualDirectory virtualDir) { // set anonymous credentials anonymAuthSvc.SetAuthenticationSettings(virtualDir.FullQualifiedPath, GetQualifiedAccountName(virtualDir.AnonymousUsername), virtualDir.AnonymousUserPassword, virtualDir.EnableAnonymousAccess); // configure "Connect As" feature if (virtualDir.ContentPath.StartsWith(@"\\")) webObjectsSvc.ConfigureConnectAsFeature(virtualDir); } /// /// Creates if needed dedicated iisAppObject pools and assigns to specified site iisAppObject pool according to /// selected ASP.NET version. /// /// WEb site to operate on. /// A value which shows whether iisAppObject pools has to be created. private void SetWebSiteApplicationPool(WebSite site, bool createAppPools) { var aphl = new WebAppPoolHelper(ProviderSettings); // Site isolation mode var sisMode = site.DedicatedApplicationPool ? SiteAppPoolMode.Dedicated : SiteAppPoolMode.Shared; // Create dedicated iisAppObject pool name for the site with installed ASP.NET version if (createAppPools && site.DedicatedApplicationPool) { // Find dedicated app pools var dedicatedPools = Array.FindAll(aphl.SupportedAppPools.ToArray(), x => aphl.isolation(x.Mode) == SiteAppPoolMode.Dedicated); // Generate dedicated iisAppObject pools names and create them. foreach (var item in dedicatedPools) { // Retrieve .NET Framework version var dotNetVersion = aphl.dotNetVersion(item.Mode); // var enable32BitAppOnWin64 = Enable32BitAppOnWin64; // Force "enable32BitAppOnWin64" set to true for .NET v1.1 if (dotNetVersion == SiteAppPoolMode.dotNetFramework1) enable32BitAppOnWin64 = true; // var poolName = WSHelper.InferAppPoolName(item.Name, site.Name, item.Mode); // Ensure we are not going to add an existing app pool if (webObjectsSvc.IsApplicationPoolExist(poolName)) continue; // using (var srvman = webObjectsSvc.GetServerManager()) { // Create iisAppObject pool var pool = srvman.ApplicationPools.Add(poolName); pool.ManagedRuntimeVersion = aphl.aspnet_runtime(item.Mode); pool.ManagedPipelineMode = aphl.runtime_pipeline(item.Mode); pool.Enable32BitAppOnWin64 = enable32BitAppOnWin64; pool.AutoStart = true; // Identity pool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser; pool.ProcessModel.UserName = GetQualifiedAccountName(site.AnonymousUsername); pool.ProcessModel.Password = site.AnonymousUserPassword; // Commit changes srvman.CommitChanges(); } } } // Find var siteAppPool = Array.Find(aphl.SupportedAppPools.ToArray(), x => x.AspNetInstalled.Equals(site.AspNetInstalled) && aphl.isolation(x.Mode) == sisMode); // Assign iisAppObject pool according to ASP.NET version installed and isolation mode specified. site.ApplicationPool = WSHelper.InferAppPoolName(siteAppPool.Name, site.Name, siteAppPool.Mode); } private void CheckEnableWritePermissions(ServerManager srvman, WebVirtualDirectory virtualDir) { string anonymousUsername = virtualDir.AnonymousUsername; // if (virtualDir.DedicatedApplicationPool) { ApplicationPool appPool = webObjectsSvc.GetApplicationPool(srvman, virtualDir); // if (appPool != null) anonymousUsername = appPool.ProcessModel.UserName; } // if (!String.IsNullOrEmpty(anonymousUsername)) virtualDir.EnableWritePermissions = CheckWriteAccessEnabled(virtualDir.ContentPath, GetNonQualifiedAccountName(anonymousUsername)); } #endregion #region IWebServer Members public override void ChangeSiteState(string siteId, ServerState state) { webObjectsSvc.ChangeSiteState(siteId, state); } public override ServerState GetSiteState(string siteId) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return GetSiteState(srvman, siteId); } } public ServerState GetSiteState(ServerManager srvman, string siteId) { return webObjectsSvc.GetSiteState(srvman, siteId); } public override bool SiteExists(string siteId) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return webObjectsSvc.SiteExists(srvman, siteId); } } public override string[] GetSites() { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return webObjectsSvc.GetSites(srvman); } } public new string GetSiteId(string siteName) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return webObjectsSvc.GetWebSiteNameFromIIS(srvman, siteName); } } public override WebSite GetSite(string siteId) { WebSite site = null; using (ServerManager srvman = webObjectsSvc.GetServerManager()) { WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings); // site = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId); // site.Bindings = webObjectsSvc.GetSiteBindings(srvman, siteId); // FillVirtualDirectoryFromIISObject(srvman, site); // FillVirtualDirectoryRestFromIISObject(srvman, site); // check frontpage site.FrontPageAvailable = IsFrontPageSystemInstalled(); site.FrontPageInstalled = IsFrontPageInstalled(srvman, siteId); //check ColdFusion if (IsColdFusionSystemInstalled()) { if (IsColdFusion7Installed()) { site.ColdFusionVersion = "7"; site.ColdFusionAvailable = true; } else { if (IsColdFusion8Installed()) { site.ColdFusionVersion = "8"; site.ColdFusionAvailable = true; } } if (IsColdFusion9Installed()) { site.ColdFusionVersion = "9"; site.ColdFusionAvailable = true; } } else { site.ColdFusionAvailable = false; } site.CreateCFVirtualDirectories = ColdFusionDirectoriesAdded(srvman, siteId); //site.ColdFusionInstalled = IsColdFusionEnabledOnSite(GetSiteId(site.Name)); // check sharepoint site.SharePointInstalled = false; // site.DedicatedApplicationPool = !aphl.is_shared_pool(site.ApplicationPool); // CheckEnableWritePermissions(srvman, site); // ReadWebManagementAccessDetails(srvman, site); // ReadWebDeployPublishingAccessDetails(site); // site.SecuredFoldersInstalled = IsSecuredFoldersInstalled(srvman, siteId); // check Helicon Ape HeliconApeStatus heliconApeStatus = GetHeliconApeStatus(srvman, siteId); site.HeliconApeInstalled = heliconApeStatus.IsInstalled; site.HeliconApeEnabled = heliconApeStatus.IsEnabled; // site.SiteState = GetSiteState(srvman, siteId); // site.SecuredFoldersInstalled = IsSecuredFoldersInstalled(srvman, siteId); // site.SiteState = GetSiteState(srvman, siteId); // } return site; } public new string[] GetSitesAccounts(string[] siteIds) { List accounts = new List(); using (ServerManager srvman = webObjectsSvc.GetServerManager()) { for (int i = 0; i < siteIds.Length; i++) { try { accounts.Add((string)anonymAuthSvc.GetAuthenticationSettings(srvman, siteIds[i])[AuthenticationGlobals.AnonymousAuthenticationUserName]); } catch (Exception ex) { Log.WriteError(String.Format("Web site {0} is either deleted or doesn't exist", siteIds[i]), ex); } } } return accounts.ToArray(); } public override ServerBinding[] GetSiteBindings(string siteId) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return webObjectsSvc.GetSiteBindings(srvman, siteId); } } public override string CreateSite(WebSite site) { // assign site id site.SiteId = site.Name; // create anonymous user CreateWebSiteAnonymousAccount(site); // Grant IIS_WPG group membership to site's anonymous account SecurityUtils.GrantLocalGroupMembership(site.AnonymousUsername, IIS_IUSRS_GROUP, ServerSettings); // set iisAppObject pools SetWebSiteApplicationPool(site, true); // set folder permissions SetWebFolderPermissions(site.ContentPath, GetNonQualifiedAccountName(site.AnonymousUsername), site.EnableWritePermissions, site.DedicatedApplicationPool); // set DATA folder permissions SetWebFolderPermissions(site.DataPath, GetNonQualifiedAccountName(site.AnonymousUsername), true, site.DedicatedApplicationPool); // qualify account name with AD Domain site.AnonymousUsername = GetQualifiedAccountName(site.AnonymousUsername); // try { // Create site webObjectsSvc.CreateSite(site); // Update web site bindings webObjectsSvc.UpdateSiteBindings(site.SiteId, site.Bindings); // Set web site logging settings webObjectsSvc.SetWebSiteLoggingSettings(site); } catch (Exception ex) { Log.WriteError(ex); } // SetAnonymousAuthentication(site); // create logs folder if not exists if (!FileUtils.DirectoryExists(site.LogsPath)) FileUtils.CreateDirectory(site.LogsPath); // FillIISObjectFromVirtualDirectory(site); // FillIISObjectFromVirtualDirectoryRest(site); // UpdateCgiBinFolder(site); // try { webObjectsSvc.ChangeSiteState(site.SiteId, ServerState.Started); } catch (Exception ex) { Log.WriteError(ex); } // return site.SiteId; } public override void UpdateSite(WebSite site) { // load original site settings WebSite origSite = GetSite(site.SiteId); // Get non-qualified anonymous account user name (eq. without domain name or machine name) string anonymousAccount = GetNonQualifiedAccountName(site.AnonymousUsername); string origAnonymousAccount = GetNonQualifiedAccountName(origSite.AnonymousUsername); // if folder has been changed if (String.Compare(origSite.ContentPath, site.ContentPath, true) != 0) RemoveWebFolderPermissions(origSite.ContentPath, origAnonymousAccount); // ensure anonumous user account exists if (!SecurityUtils.UserExists(anonymousAccount, ServerSettings, UsersOU)) { CreateWebSiteAnonymousAccount(site); } anonymousAccount = GetNonQualifiedAccountName(site.AnonymousUsername); // Grant IIS_IUSRS group membership if (!SecurityUtils.HasLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings, UsersOU)) { SecurityUtils.GrantLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings); } // bool appPoolFlagChanged = origSite.DedicatedApplicationPool != site.DedicatedApplicationPool; // check if we need to remove dedicated app pools bool deleteDedicatedPools = (appPoolFlagChanged && !site.DedicatedApplicationPool); // SetWebSiteApplicationPool(site, false); // if (!webObjectsSvc.IsApplicationPoolExist(site.ApplicationPool) && site.DedicatedApplicationPool) { // CREATE dedicated pool SetWebSiteApplicationPool(site, true); } // FillIISObjectFromVirtualDirectory(site); // FillIISObjectFromVirtualDirectoryRest(site); // set logs folder permissions if (!FileUtils.DirectoryExists(site.LogsPath)) FileUtils.CreateDirectory(site.LogsPath); // Update website webObjectsSvc.UpdateSite(site); // Update website bindings webObjectsSvc.UpdateSiteBindings(site.SiteId, site.Bindings); // Set website logging settings webObjectsSvc.SetWebSiteLoggingSettings(site); // UpdateCgiBinFolder(site); // TO-DO // update all child virtual directories to use new pool if (appPoolFlagChanged) { WebVirtualDirectory[] dirs = GetVirtualDirectories(site.SiteId); foreach (WebVirtualDirectory dir in dirs) { // set dedicated pool flag //dir.DedicatedApplicationPool = site.DedicatedApplicationPool; WebVirtualDirectory vdir = GetVirtualDirectory(site.SiteId, dir.Name); vdir.AspNetInstalled = site.AspNetInstalled; vdir.ApplicationPool = site.ApplicationPool; // update iisDirObject UpdateVirtualDirectory(site.SiteId, vdir); } // Enforce Web Deploy publishing settings if enabled to ensure we use correct settings all the time if (site.WebDeploySitePublishingEnabled == true) { EnforceDelegationRulesRestrictions(site.Name, site.WebDeployPublishingAccount); } } #region ColdFusion Virtual Directories using (ServerManager srvman = webObjectsSvc.GetServerManager()) { //TODO: NANOFIX:Added the If block and put the rest of the code in the else block(For Virtual Directory) if (string.IsNullOrEmpty(base.CFFlashRemotingDirPath)) { DeleteCFVirtualDirectories(site.SiteId); site.CreateCFVirtualDirectories = false; } else { if (ColdFusionDirectoriesAdded(srvman, site.SiteId)) { if (!site.CreateCFVirtualDirectories) { DeleteCFVirtualDirectories(site.SiteId); site.CreateCFVirtualDirectories = false; } } else { if (site.CreateCFVirtualDirectories) { CreateCFVirtualDirectories(site.SiteId); site.CreateCFVirtualDirectories = true; } } } } #endregion #region ColdFusionHandlerFix //TODO: NANOFIX: Region Added for Cold Fusion Handler Fix using (ServerManager srvman = webObjectsSvc.GetServerManager()) { var appConfig = srvman.GetApplicationHostConfiguration(); ConfigurationSection handlersSection = appConfig.GetSection(Constants.HandlersSection, (site as WebVirtualDirectory).FullQualifiedPath); var handlersCollection = handlersSection.GetCollection(); List cfElementList = new List(); foreach (var action in handlersCollection) { var name = action["name"].ToString(); if (string.Compare(name, "coldfusion", true) == 0) { cfElementList.Add(action); } } foreach (var e in cfElementList) { handlersCollection.Remove(e); } if (site.ColdFusionInstalled) { var cfElement = handlersCollection.CreateElement("add"); cfElement["name"] = "coldfusion"; cfElement["modules"] = "IsapiModule"; cfElement["path"] = "*"; cfElement["scriptProcessor"] = base.ColdFusionPath; cfElement["verb"] = "*"; cfElement["resourceType"] = "Unspecified"; cfElement["requireAccess"] = "None"; cfElement["preCondition"] = "bitness64"; handlersCollection.AddAt(0, cfElement); } srvman.CommitChanges(); } #endregion // remove dedicated pools if any if (deleteDedicatedPools) DeleteDedicatedPoolsAllocated(site.Name); // set WEB folder permissions SetWebFolderPermissions(site.ContentPath, anonymousAccount, site.EnableWritePermissions, site.DedicatedApplicationPool); // set DATA folder permissions SetWebFolderPermissions(site.DataPath, anonymousAccount, true, site.DedicatedApplicationPool); } /// /// Updates site's bindings with supplied ones. /// /// Site's id to update bindings for. /// Bindings information. public override void UpdateSiteBindings(string siteId, ServerBinding[] bindings) { this.webObjectsSvc.UpdateSiteBindings(siteId, bindings); } /// /// Deletes site with specified id. /// /// Site's id to be deleted. public override void DeleteSite(string siteId) { // Load site description. WebSite site = this.GetSite(siteId); #region Fix for bug #594 // Disable Remote Management Access and revoke access permissions if any if (IsWebManagementServiceInstalled() && IsWebManagementAccessEnabled(site)) { RevokeWebManagementAccess(siteId, site[WebSite.WmSvcAccountName]); } #endregion // Disable Web Deploy publishing functionality and revoke access permissions if any if (IsWebDeployInstalled() && site.WebDeploySitePublishingEnabled) { RevokeWebDeployPublishingAccess(site.SiteId, site.WebDeployPublishingAccount); } // Get non-qualified account name string anonymousAccount = GetNonQualifiedAccountName(site.AnonymousUsername); // Remove unnecessary permissions. RemoveWebFolderPermissions(site.ContentPath, anonymousAccount); // Stop web site webObjectsSvc.ChangeSiteState(site.Name, ServerState.Stopped); Log.WriteInfo(String.Format("Site {0} was stopped before deleting.", site.Name)); // Delete site in IIS webObjectsSvc.DeleteSite(siteId); // Delete dedicated pool if required if (site.DedicatedApplicationPool) { DeleteDedicatedPoolsAllocated(site.Name); } // ensure anonymous account is shared account if (!String.Equals("IUSR", anonymousAccount)) { // Revoke IIS_IUSRS membership first if (SecurityUtils.HasLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings, UsersOU)) { SecurityUtils.RevokeLocalGroupMembership(anonymousAccount, IIS_IUSRS_GROUP, ServerSettings); } // delete anonymous user account if (SecurityUtils.UserExists(anonymousAccount, ServerSettings, UsersOU)) { SecurityUtils.DeleteUser(anonymousAccount, ServerSettings, UsersOU); } } } /// /// Checks whether virtual iisDirObject with supplied name under specified site exists. /// /// Site id. /// Directory name to check. /// true - if it exists; false - otherwise. public override bool VirtualDirectoryExists(string siteId, string directoryName) { return this.webObjectsSvc.VirtualDirectoryExists(siteId, directoryName); } /// /// Gets virtual directories that belong to site with supplied id. /// /// Site's id to get virtual directories for. /// virtual directories that belong to site with supplied id. public override WebVirtualDirectory[] GetVirtualDirectories(string siteId) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return GetVirtualDirectories(srvman, siteId); } } private WebVirtualDirectory[] GetVirtualDirectories(ServerManager srvman, string siteId) { // get all virt dirs WebVirtualDirectory[] virtDirs = webObjectsSvc.GetVirtualDirectories(srvman, siteId); // filter string sharedToolsFolder = GetMicrosoftSharedFolderPath(); List result = new List(); foreach (WebVirtualDirectory dir in virtDirs) { // check if this is a system (FrontPage or SharePoint) virtual iisDirObject if (!String.IsNullOrEmpty(sharedToolsFolder) && dir.ContentPath.ToLower().StartsWith(sharedToolsFolder.ToLower())) continue; result.Add(dir); } return result.ToArray(); } /// /// Gets virtual iisDirObject description that belongs to site with supplied id and has specified name. /// /// Site's id that owns virtual iisDirObject. /// Directory's name to get description for. /// virtual iisDirObject description that belongs to site with supplied id and has specified name. public override WebVirtualDirectory GetVirtualDirectory(string siteId, string directoryName) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings); // WebVirtualDirectory webVirtualDirectory = webObjectsSvc.GetVirtualDirectory(siteId, directoryName); // this.FillVirtualDirectoryFromIISObject(srvman, webVirtualDirectory); this.FillVirtualDirectoryRestFromIISObject(srvman, webVirtualDirectory); // webVirtualDirectory.DedicatedApplicationPool = !aphl.is_shared_pool(webVirtualDirectory.ApplicationPool); // CheckEnableWritePermissions(srvman, webVirtualDirectory); // ReadWebManagementAccessDetails(srvman, webVirtualDirectory); // ReadWebDeployPublishingAccessDetails(webVirtualDirectory); // return webVirtualDirectory; } } /// /// Creates virtual iisDirObject under site with specified id. /// /// Site's id to create virtual iisDirObject under. /// Virtual iisDirObject description. public override void CreateVirtualDirectory(string siteId, WebVirtualDirectory directory) { // Create iisDirObject folder if not exists. if (!FileUtils.DirectoryExists(directory.ContentPath)) { FileUtils.CreateDirectory(directory.ContentPath); } // WebSite webSite = GetSite(siteId); // copy props from parent site directory.ParentSiteName = siteId; directory.AspNetInstalled = webSite.AspNetInstalled; directory.ApplicationPool = webSite.ApplicationPool; // Create record in IIS's configuration. webObjectsSvc.CreateVirtualDirectory(siteId, directory.VirtualPath, directory.ContentPath); using (ServerManager srvman = webObjectsSvc.GetServerManager()) { PropertyBag bag = anonymAuthSvc.GetAuthenticationSettings(srvman, siteId); directory.AnonymousUsername = (string)bag[AuthenticationGlobals.AnonymousAuthenticationUserName]; directory.AnonymousUserPassword = (string)bag[AuthenticationGlobals.AnonymousAuthenticationPassword]; directory.EnableAnonymousAccess = (bool)bag[AuthenticationGlobals.Enabled]; // Update virtual iisDirObject. this.UpdateVirtualDirectory(siteId, directory); } } /// /// Updates virtual iisDirObject settings. /// /// Site's id that owns supplied iisDirObject. /// Web iisDirObject that needs to be updated. public override void UpdateVirtualDirectory(string siteId, WebVirtualDirectory directory) { string origPath = null; using (ServerManager srvman = webObjectsSvc.GetServerManager()) { if (!this.webObjectsSvc.SiteExists(srvman, siteId)) return; // get original path origPath = webObjectsSvc.GetPhysicalPath(srvman, directory); } WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings); // bool dedicatedPool = !aphl.is_shared_pool(directory.ApplicationPool); // SiteAppPoolMode sisMode = dedicatedPool ? SiteAppPoolMode.Dedicated : SiteAppPoolMode.Shared; // directory.ParentSiteName = siteId; // remove unnecessary permissions // if original folder has been changed if (String.Compare(origPath, directory.ContentPath, true) != 0) RemoveWebFolderPermissions(origPath, GetNonQualifiedAccountName(directory.AnonymousUsername)); // set folder permissions SetWebFolderPermissions(directory.ContentPath, GetNonQualifiedAccountName(directory.AnonymousUsername), directory.EnableWritePermissions, dedicatedPool); // var pool = Array.Find(aphl.SupportedAppPools.ToArray(), x => x.AspNetInstalled.Equals(directory.AspNetInstalled) && aphl.isolation(x.Mode) == sisMode); // Assign to virtual iisDirObject iisAppObject pool directory.ApplicationPool = WSHelper.InferAppPoolName(pool.Name, siteId, pool.Mode); // webObjectsSvc.UpdateVirtualDirectory(directory); // this.FillIISObjectFromVirtualDirectory(directory); this.FillIISObjectFromVirtualDirectoryRest(directory); } /// /// Deletes virtual iisDirObject within specified site. /// /// Site id. /// Directory name to delete. public override void DeleteVirtualDirectory(string siteId, string directoryName) { var virtualDir = new WebVirtualDirectory { ParentSiteName = siteId, Name = directoryName }; // webObjectsSvc.DeleteVirtualDirectory(virtualDir); anonymAuthSvc.RemoveAuthenticationSettings(virtualDir.FullQualifiedPath); } public new void GrantWebSiteAccess(string path, string siteId, NTFSPermission permission) { // TODO } #endregion #region IISPassword protected override bool IsSecuredFoldersInstalled(string siteId) { using (var srvman = webObjectsSvc.GetServerManager()) { return IsSecuredFoldersInstalled(srvman, siteId); } } private bool IsSecuredFoldersInstalled(ServerManager srvman, string siteId) { var appConfig = srvman.GetApplicationHostConfiguration(); // var modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId); // var modulesCollection = modulesSection.GetCollection(); // foreach (var moduleEntry in modulesCollection) { if (String.Equals(moduleEntry["name"].ToString(), Constants.WEBSITEPANEL_IISMODULES, StringComparison.InvariantCultureIgnoreCase)) return true; } // return false; } protected override string GetSiteContentPath(string siteId) { using (var srvman = webObjectsSvc.GetServerManager()) { return GetSiteContentPath(srvman, siteId); } } protected string GetSiteContentPath(ServerManager srvman, string siteId) { var webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId); // if (webSite != null) return webObjectsSvc.GetPhysicalPath(srvman, webSite); // return String.Empty; } /// /// /// /// /// /// public override void InstallSecuredFolders(string siteId) { using (var srvman = webObjectsSvc.GetServerManager()) { // if (String.IsNullOrEmpty(siteId)) throw new ArgumentNullException("siteId"); // WebsitePanel.IIsModules works for apps working in Integrated Pipeline mode #region Switch automatically to the app pool with Integrated Pipeline enabled var webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId); // if (webSite == null) throw new ApplicationException(String.Format("Could not find a web site with the following identifier: {0}.", siteId)); // var aphl = new WebAppPoolHelper(ProviderSettings); // Fill ASP.NET settings FillAspNetSettingsFromIISObject(srvman, webSite); // var currentPool = aphl.match_webapp_pool(webSite); var dotNetVersion = aphl.dotNetVersion(currentPool.Mode); var sisMode = aphl.isolation(currentPool.Mode); // AT least ASP.NET 2.0 is allowed to provide such capabilities... if (dotNetVersion == SiteAppPoolMode.dotNetFramework1) dotNetVersion = SiteAppPoolMode.dotNetFramework2; // and Integrated pipeline... if (aphl.pipeline(currentPool.Mode) != SiteAppPoolMode.Integrated) { // Lookup for the opposite pool matching the criteria var oppositePool = Array.Find(aphl.SupportedAppPools.ToArray(), x => aphl.dotNetVersion(x.Mode) == dotNetVersion && aphl.isolation(x.Mode) == sisMode && aphl.pipeline(x.Mode) == SiteAppPoolMode.Integrated); // webSite.AspNetInstalled = oppositePool.AspNetInstalled; // SetWebSiteApplicationPool(webSite, false); // var iisSiteObject = srvman.Sites[siteId]; iisSiteObject.Applications["/"].ApplicationPoolName = webSite.ApplicationPool; // srvman.CommitChanges(); } } #endregion #region Disable automatically Integrated Windows Authentication // using (var srvman = webObjectsSvc.GetServerManager()) { PropertyBag winAuthBag = winAuthSvc.GetAuthenticationSettings(srvman, siteId); // if ((bool)winAuthBag[AuthenticationGlobals.Enabled]) { Configuration config = srvman.GetApplicationHostConfiguration(); ConfigurationSection windowsAuthenticationSection = config.GetSection( "system.webServer/security/authentication/windowsAuthentication", siteId); // windowsAuthenticationSection["enabled"] = false; // srvman.CommitChanges(); } } #endregion // using (var srvman = webObjectsSvc.GetServerManager()) { // Configuration appConfig = srvman.GetApplicationHostConfiguration(); // ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId); // ConfigurationElementCollection modulesCollection = modulesSection.GetCollection(); // ConfigurationElement moduleAdd = modulesCollection.CreateElement("add"); // moduleAdd["name"] = Constants.WEBSITEPANEL_IISMODULES; moduleAdd["type"] = SecureFoldersModuleAssembly; // Enable module for all content despite ASP.NET is enabled or not moduleAdd["preCondition"] = ""; // modulesCollection.Add(moduleAdd); // srvman.CommitChanges(); } } public override void UninstallSecuredFolders(string siteId) { // if (String.IsNullOrEmpty(siteId)) throw new ArgumentNullException("siteId"); // using (var srvman = webObjectsSvc.GetServerManager()) { // Configuration appConfig = srvman.GetApplicationHostConfiguration(); // ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId); // ConfigurationElementCollection modulesCollection = modulesSection.GetCollection(); // ConfigurationElement iisModulesEntry = null; // foreach (ConfigurationElement moduleEntry in modulesCollection) { if (String.Equals(moduleEntry["name"].ToString(), Constants.WEBSITEPANEL_IISMODULES, StringComparison.InvariantCultureIgnoreCase)) { iisModulesEntry = moduleEntry; break; } } // if (iisModulesEntry != null) { modulesCollection.Remove(iisModulesEntry); srvman.CommitChanges(); } } } #endregion #region Helicon Ape public override HeliconApeStatus GetHeliconApeStatus(string siteId) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return GetHeliconApeStatus(srvman, siteId); } } private HeliconApeStatus GetHeliconApeStatus(ServerManager srvman, string siteId) { string installDir = GetHeliconApeInstallDir(siteId); string registrationInfo = GetRegistrationInfo(siteId, installDir); return new HeliconApeStatus { IsEnabled = IsHeliconApeEnabled(srvman, siteId), InstallDir = installDir, IsInstalled = IsHeliconApeInstalled(srvman, siteId, installDir), Version = GetHeliconApeVersion(siteId, installDir), IsRegistered = IsHeliconApeRegistered(siteId, registrationInfo), RegistrationInfo = registrationInfo }; } private bool IsHeliconApeEnabled(ServerManager srvman, string siteId) { var appConfig = srvman.GetApplicationHostConfiguration(); var modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId); var modulesCollection = modulesSection.GetCollection(); foreach (var moduleEntry in modulesCollection) { if (String.Equals(moduleEntry["name"].ToString(), Constants.HeliconApeModule, StringComparison.InvariantCultureIgnoreCase)) return true; } // return false; } /// /// Creates the specified account and grants it Web Publishing Access permissions /// /// Web site name to enable Web Publishing Access at /// User name to grant the access for /// User password public new void GrantWebDeployPublishingAccess(string siteName, string accountName, string accountPassword) { // Web Publishing Access feature requires FullControl permissions on the web site's wwwroot folder GrantWebManagementAccessInternally(siteName, accountName, accountPassword, NTFSPermission.FullControl); // EnforceDelegationRulesRestrictions(siteName, accountName); } /// /// Creates the specified account and grants it Web Publishing Access permissions /// /// Web site name to enable Web Publishing Access at /// User name to grant the access for /// User password public new void RevokeWebDeployPublishingAccess(string siteName, string accountName) { // Web Publishing Access feature requires FullControl permissions on the web site's wwwroot folder RevokeWebManagementAccess(siteName, accountName); // RemoveDelegationRulesRestrictions(siteName, accountName); } private void RemoveDelegationRulesRestrictions(string siteName, string accountName) { WebSite webSite = null; using (ServerManager srvman = webObjectsSvc.GetServerManager()) { webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName); } var moduleService = new DelegationRulesModuleService(); // Adjust web publishing permissions to the user accordingly to deny some rules for shared app pools var fqUsername = GetFullQualifiedAccountName(accountName); // Instantiate application pool helper to retrieve the app pool mode web site is running in WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings); // // Shared app pool is a subject restrictions to change ASP.NET version and recycle the pool, // so we need to remove these restrictions if (aphl.is_shared_pool(webSite.ApplicationPool) == true) { // moduleService.RemoveUserFromRule("recycleApp", "{userScope}", fqUsername); moduleService.RemoveUserFromRule("appPoolPipeline,appPoolNetFx", "{userScope}", fqUsername); } } public void EnforceDelegationRulesRestrictions(string siteName, string accountName) { WebSite webSite = null; using (ServerManager srvman = webObjectsSvc.GetServerManager()) { webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName); } var moduleService = new DelegationRulesModuleService(); // Adjust web publishing permissions to the user accordingly to deny some rules for shared app pools var fqUsername = GetFullQualifiedAccountName(accountName); // Instantiate application pool helper to retrieve the app pool mode web site is running in WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings); // Shared app pool is a subject restrictions to change ASP.NET version and recycle the pool if (aphl.is_shared_pool(webSite.ApplicationPool) == true) { // moduleService.RestrictRuleToUser("recycleApp", "{userScope}", fqUsername); moduleService.RestrictRuleToUser("appPoolPipeline,appPoolNetFx", "{userScope}", fqUsername); } // Dedicated app pool is not a subject for any restrictions else { // moduleService.AllowRuleToUser("recycleApp", "{userScope}", fqUsername); moduleService.AllowRuleToUser("appPoolPipeline,appPoolNetFx", "{userScope}", fqUsername); } } private string GetHeliconApeInstallDir(string siteId) { //Check global registration return Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Helicon\\Ape", "InstallDir", string.Empty) as string; } private bool IsHeliconApeInstalled(ServerManager srvman, string siteId, string installDir) { //Check global registration bool result = !string.IsNullOrEmpty(installDir); if (!result && !string.IsNullOrEmpty(siteId)) { //Check per-site installation string sitepath = GetSiteContentPath(srvman, siteId); string dllPath = Path.Combine(sitepath, "Bin\\Helicon.Ape.dll"); result = File.Exists(dllPath); } return result; } private static string HELICON_APE_NOT_REGISTERED = "Not registered"; private string GetHeliconApeVersion(string siteId, string installDir) { if (string.IsNullOrEmpty(installDir)) return HELICON_APE_NOT_REGISTERED; return System.Diagnostics.FileVersionInfo.GetVersionInfo(Path.Combine(installDir, "Helicon.Ape.Editor.dll")).FileVersion; } private string GetHeliconApeModuleType(string siteId) { string installDir = GetHeliconApeInstallDir(siteId); string version = GetHeliconApeVersion(siteId, installDir); if (version.Equals(HELICON_APE_NOT_REGISTERED)) { // Ape installed for site return "Helicon.Ape.ApeModule"; } else { // Ape installed globally in GAC // return full type with version return string.Format( "Helicon.Ape.ApeModule, Helicon.Ape, Version={0}, Culture=neutral, PublicKeyToken=95bfbfd1a38437eb", version); } } private string GetHeliconApeHandlerType(string siteId) { string installDir = GetHeliconApeInstallDir(siteId); string version = GetHeliconApeVersion(siteId, installDir); if (version.Equals(HELICON_APE_NOT_REGISTERED)) { // Ape installed for site return "Helicon.Ape.Handler"; } else { // Ape installed globally in GAC // return full type with version return string.Format( "Helicon.Ape.Handler, Helicon.Ape, Version={0}, Culture=neutral, PublicKeyToken=95bfbfd1a38437eb", version); } } private string FindregistrationInfo(string path) { System.Text.RegularExpressions.Regex reRegistrationName = new System.Text.RegularExpressions.Regex("^\\s*RegistrationName\\s*=\\s*([^#=]+)\\s*(?:#.*)?", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.CultureInvariant | System.Text.RegularExpressions.RegexOptions.Compiled); string registrationName = ""; using (StreamReader sr = File.OpenText(path)) { while (sr.Peek() >= 0) { string line = sr.ReadLine(); if (reRegistrationName.Match(line).Success) { registrationName = reRegistrationName.Match(line).Groups[1].Value; if ( !string.IsNullOrEmpty(registrationName) ) { return string.Format("Registered to: {0}", registrationName); } break; } } } //Not found return string.Empty; } private string GetRegistrationInfo(string siteId, string installDir) { if (string.IsNullOrEmpty(installDir)) return string.Empty; string registrationInfo = FindregistrationInfo(Path.Combine(installDir, "licenses.conf")); if (!string.IsNullOrEmpty(registrationInfo)) return registrationInfo; registrationInfo = FindregistrationInfo(Path.Combine(installDir, "httpd.conf")); if (!string.IsNullOrEmpty(registrationInfo)) return registrationInfo; long dtFirstRunBinary = (long)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Helicon\\Ape", "FirstRun", 0L); DateTime dtFirstRun; if (0 == dtFirstRunBinary) { dtFirstRun = DateTime.Now; Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Helicon\\Ape", "FirstRun", dtFirstRun.ToBinary(),RegistryValueKind.QWord ); } else { dtFirstRun = DateTime.FromBinary(dtFirstRunBinary); } int trialDays = 45 - (DateTime.Now - dtFirstRun).Days; if (trialDays < 0) trialDays = 0; return string.Format("Trial days left: {0}", trialDays); } private bool IsHeliconApeRegistered(string siteId, string registrationInfo) { if (string.IsNullOrEmpty(registrationInfo)) return false; return registrationInfo.StartsWith("Registered to:"); } public override void EnableHeliconApe(string siteId) { WebSite webSite = null; using (ServerManager srvman = webObjectsSvc.GetServerManager()) { // if (String.IsNullOrEmpty(siteId)) throw new ArgumentNullException("siteId"); // Helicon.Ape.ApeModule works for apps working in Integrated Pipeline mode // Switch automatically to the app pool with Integrated Pipeline enabled webSite = webObjectsSvc.GetWebSiteFromIIS(srvman, siteId); // if (webSite == null) throw new ApplicationException(String.Format("Could not find a web site with the following identifier: {0}.", siteId)); // Fill ASP.NET settings FillAspNetSettingsFromIISObject(srvman, webSite); } // var aphl = new WebAppPoolHelper(ProviderSettings); var currentPool = aphl.match_webapp_pool(webSite); var dotNetVersion = aphl.dotNetVersion(currentPool.Mode); var sisMode = aphl.isolation(currentPool.Mode); // AT least ASP.NET 2.0 is allowed to provide such capabilities... if (dotNetVersion == SiteAppPoolMode.dotNetFramework1) dotNetVersion = SiteAppPoolMode.dotNetFramework2; // and Integrated pipeline... if (aphl.pipeline(currentPool.Mode) != SiteAppPoolMode.Integrated) { // Lookup for the opposite pool matching the criteria var oppositePool = Array.Find(aphl.SupportedAppPools.ToArray(), x => aphl.dotNetVersion(x.Mode) == dotNetVersion && aphl.isolation(x.Mode) == sisMode && aphl.pipeline(x.Mode) == SiteAppPoolMode.Integrated); // webSite.AspNetInstalled = oppositePool.AspNetInstalled; // SetWebSiteApplicationPool(webSite, false); // using (var srvman = webObjectsSvc.GetServerManager()) { var iisSiteObject = srvman.Sites[siteId]; iisSiteObject.Applications["/"].ApplicationPoolName = webSite.ApplicationPool; // srvman.CommitChanges(); } } #region Disable automatically Integrated Windows Authentication using (var srvman = webObjectsSvc.GetServerManager()) { PropertyBag winAuthBag = winAuthSvc.GetAuthenticationSettings(srvman, siteId); // if ((bool)winAuthBag[AuthenticationGlobals.Enabled]) { Configuration config = srvman.GetApplicationHostConfiguration(); ConfigurationSection windowsAuthenticationSection = config.GetSection( "system.webServer/security/authentication/windowsAuthentication", siteId); // windowsAuthenticationSection["enabled"] = false; // srvman.CommitChanges(); } } #endregion #region Disable automatically Secured Folders if (IsSecuredFoldersInstalled(siteId)) { UninstallSecuredFolders(siteId); } #endregion // using (var srvman = webObjectsSvc.GetServerManager()) { // Configuration appConfig = srvman.GetApplicationHostConfiguration(); // add Helicon.Ape module ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId); ConfigurationElementCollection modulesCollection = modulesSection.GetCollection(); ConfigurationElement moduleAdd = modulesCollection.CreateElement("add"); moduleAdd["name"] = Constants.HeliconApeModule; moduleAdd["type"] = GetHeliconApeModuleType(siteId); // modulesCollection.Add(moduleAdd); // add Helicon.Ape handler ConfigurationSection handlersSection = appConfig.GetSection(Constants.HandlersSection, siteId); ConfigurationElementCollection handlersCollection = handlersSection.GetCollection(); ConfigurationElement handlerAdd = handlersCollection.CreateElement("add"); handlerAdd["name"] = Constants.HeliconApeModule; handlerAdd["type"] = GetHeliconApeHandlerType(siteId); handlerAdd["path"] = Constants.HeliconApeHandlerPath; handlerAdd["verb"] = "*"; handlerAdd["resourceType"] = "Unspecified"; // handlersCollection.Add(handlerAdd); // srvman.CommitChanges(); } } public override void DisableHeliconApe(string siteId) { // if (String.IsNullOrEmpty(siteId)) throw new ArgumentNullException("siteId"); // using (var srvman = webObjectsSvc.GetServerManager()) { // Configuration appConfig = srvman.GetApplicationHostConfiguration(); // remove Helicon.Ape module ConfigurationSection modulesSection = appConfig.GetSection(Constants.ModulesSection, siteId); ConfigurationElementCollection modulesCollection = modulesSection.GetCollection(); ConfigurationElement htaccessModuleEntry = null; foreach (ConfigurationElement moduleEntry in modulesCollection) { if (String.Equals(moduleEntry["name"].ToString(), Constants.HeliconApeModule, StringComparison.InvariantCultureIgnoreCase)) { htaccessModuleEntry = moduleEntry; break; } } if (htaccessModuleEntry != null) { modulesCollection.Remove(htaccessModuleEntry); } // remove Helicon.Ape handler ConfigurationSection handlersSection = appConfig.GetSection(Constants.HandlersSection, siteId); ConfigurationElementCollection handlersCollection = handlersSection.GetCollection(); ConfigurationElement htaccessHandlerEntry = null; foreach (ConfigurationElement handlerEntry in handlersCollection) { if (String.Equals(handlerEntry["name"].ToString(), Constants.HeliconApeModule, StringComparison.InvariantCultureIgnoreCase)) { htaccessHandlerEntry = handlerEntry; break; } } // if (htaccessHandlerEntry != null) { handlersCollection.Remove(htaccessHandlerEntry); } // commit changes to metabase if (htaccessModuleEntry != null || htaccessHandlerEntry != null) { srvman.CommitChanges(); } } } public override List GetHeliconApeFolders(string siteId) { string siteRootPath = GetSiteContentPath(siteId); List folders = new List(); // walk through the virtual directories WebVirtualDirectory[] virtualDirectories = GetVirtualDirectories(siteId); foreach (WebVirtualDirectory webVirtualDirectory in virtualDirectories) { HtaccessFolder.GetDirectoriesWithHtaccess(siteRootPath, "\\" + webVirtualDirectory.FullQualifiedPath, webVirtualDirectory.ContentPath, webVirtualDirectory.ContentPath, folders); } // walk through the filesystem HtaccessFolder.GetDirectoriesWithHtaccess(siteRootPath, "", siteRootPath, siteRootPath, folders); folders.Sort(); return folders; } public override HtaccessFolder GetHeliconApeFolder(string siteId, string folderPath) { // search folder List htaccessFolders = GetHeliconApeFolders(siteId); foreach (HtaccessFolder htaccessFolder in htaccessFolders) { if (string.Equals(folderPath, htaccessFolder.Path, StringComparison.OrdinalIgnoreCase)) { htaccessFolder.ReadHtaccess(); return htaccessFolder; } } // create new htaccess folder return HtaccessFolder.CreateHtaccessFolder(GetSiteContentPath(siteId), folderPath); } public override HtaccessFolder GetHeliconApeHttpdFolder() { return HtaccessFolder.CreateHttpdConfFolder(GetHeliconApeInstallDir("-1")); } public override void UpdateHeliconApeFolder(string siteId, HtaccessFolder folder) { if (null != folder) { if (string.IsNullOrEmpty(folder.ContentPath)) { HtaccessFolder newFolder = GetHeliconApeFolder(siteId, folder.Path); newFolder.HtaccessContent = folder.HtaccessContent; newFolder.Update(); } else { if (string.IsNullOrEmpty(folder.SiteRootPath)) { folder.SiteRootPath = GetSiteContentPath(siteId); } folder.Update(); } } } public override void UpdateHeliconApeHttpdFolder(HtaccessFolder folder) { if (null != folder) { HtaccessFolder newFolder = GetHeliconApeHttpdFolder(); newFolder.HtaccessContent = folder.HtaccessContent; newFolder.Update(); } } public override void DeleteHeliconApeFolder(string siteId, string folderPath) { string rootPath = GetSiteContentPath(siteId); string contentPath = Path.Combine(rootPath, folderPath); string htaccessPath = Path.Combine(contentPath, HtaccessFolder.HTACCESS_FILE); if (File.Exists(htaccessPath)) { File.Delete(htaccessPath); } return; } #endregion #region Secured Helicon Ape Users public static string GeneratePasswordHash(HtaccessUser user) { if (HtaccessFolder.AUTH_TYPE_BASIC == user.AuthType) { // BASIC switch (user.EncType) { case HtaccessUser.ENCODING_TYPE_APACHE_MD5: return PasswdHelper.MD5Encode(user.Password, PasswdHelper.GetRandomSalt()); case HtaccessUser.ENCODING_TYPE_SHA1: return PasswdHelper.SHA1Encode(user.Password); case HtaccessUser.ENCODING_TYPE_UNIX_CRYPT: default: BsdDES bsdDes = new BsdDES(); return bsdDes.Crypt(user.Password); } } // DIGEST return string.Format("{0}:{1}", user.Realm, PasswdHelper.DigestEncode(user.Name, user.Password, user.Realm)); } public override List GetHeliconApeUsers(string siteId) { string rootPath = GetSiteContentPath(siteId); List users = new List(); //users.Add(new WebUser {Name = HtaccessFolder.VALID_USER}); // load users file string usersPath = Path.Combine(rootPath, HtaccessFolder.HTPASSWDS_FILE); List lines = HtaccessFolder.ReadLinesFile(usersPath); // iterate through all lines for (int i = 0; i < lines.Count; i++) { string line = lines[i]; int colonIdx = line.IndexOf(":"); if (colonIdx != -1) { string username = line.Substring(0, colonIdx); // add it to the return collection users.Add(GetHeliconApeUser(siteId, username)); } } return users; } public override HtaccessUser GetHeliconApeUser(string siteId, string userName) { // load users file string rootPath = GetSiteContentPath(siteId); string usersPath = Path.Combine(rootPath, HtaccessFolder.HTPASSWDS_FILE); List lines = HtaccessFolder.ReadLinesFile(usersPath); // iterate through all lines HtaccessUser user = null; for (int i = 0; i < lines.Count; i++) { string line = lines[i]; int colonIdx = line.IndexOf(":"); if (colonIdx != -1) { string username = line.Substring(0, colonIdx); string password = line.Substring(colonIdx + 1); if (String.Compare(username, userName, true) == 0) { // exists user = new HtaccessUser(); user.Name = username; user.Password = password; break; } } } if (user == null) return null; // user doesn't exist List userGroups = new List(); // read groups information // open groups file string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE); List groupLines = HtaccessFolder.ReadLinesFile(groupsPath); for (int i = 0; i < groupLines.Count; i++) { string groupLine = groupLines[i]; int colonIdx = groupLine.IndexOf(":"); if (colonIdx != -1) { string groupName = groupLine.Substring(0, colonIdx); string[] groupMembers = groupLine.Substring(colonIdx + 1).Split(' '); // check group members for (int j = 0; j < groupMembers.Length; j++) { if (String.Compare(groupMembers[j], user.Name, true) == 0) { userGroups.Add(groupName); break; } } } } // end iterating groups user.Groups = userGroups.ToArray(); return user; } public override void UpdateHeliconApeUser(string siteId, HtaccessUser user) { UpdateHeliconApeUser(siteId, user, false); } private void UpdateHeliconApeUser(string siteId, HtaccessUser user, bool deleteUser) { if (HtaccessFolder.VALID_USER == user.Name) return; string rootPath = GetSiteContentPath(siteId); string usersPath = Path.Combine(rootPath, HtaccessFolder.HTPASSWDS_FILE); // load users file List lines = HtaccessFolder.ReadLinesFile(usersPath); // check if the user already exists List updatedLines = new List(); bool exists = false; for (int i = 0; i < lines.Count; i++) { string line = lines[i]; string updatedLine = line; int colonIdx = line.IndexOf(":"); if (colonIdx != -1) { string username = line.Substring(0, colonIdx); string password = line.Substring(colonIdx + 1); if (String.Compare(username, user.Name, true) == 0) { // already exists exists = true; // check if we need to delete this user if (deleteUser) continue; // change password if required if (!String.IsNullOrEmpty(user.Password)) { // hash password password = GeneratePasswordHash(user); // update line updatedLine = username + ":" + password; } } } updatedLines.Add(updatedLine); } if (!exists && !deleteUser) { // new user has been added updatedLines.Add(user.Name + ":" + GeneratePasswordHash(user)); } // save users file HtaccessFolder.WriteLinesFile(usersPath, updatedLines); if (user.Groups == null) user.Groups = new string[] { }; // update groups // open groups file string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE); List groupLines = HtaccessFolder.ReadLinesFile(groupsPath); for (int i = 0; i < groupLines.Count; i++) { string groupLine = groupLines[i]; int colonIdx = groupLine.IndexOf(":"); if (colonIdx != -1) { string groupName = groupLine.Substring(0, colonIdx); string[] groupMembers = groupLine.Substring(colonIdx + 1).Split(' '); // check if user is assigned to this group bool assigned = false; for (int j = 0; j < user.Groups.Length; j++) { if (String.Compare(user.Groups[j], groupName, true) == 0) { assigned = true; break; } } // remove current user List updatedMembers = new List(); for (int j = 0; j < groupMembers.Length; j++) { // user exists in the members // check if he should be really added to this group if (String.Compare(groupMembers[j], user.Name, true) == 0) continue; updatedMembers.Add(groupMembers[j]); } if (assigned) updatedMembers.Add(user.Name); // modify group line groupLines[i] = groupName + ":" + String.Join(" ", updatedMembers.ToArray()); } } // end iterating groups // save group file HtaccessFolder.WriteLinesFile(groupsPath, groupLines); } public override void DeleteHeliconApeUser(string siteId, string userName) { string rootPath = GetSiteContentPath(siteId); HtaccessUser user = new HtaccessUser(); user.Name = userName; // update users and groups UpdateHeliconApeUser(siteId, user, true); // update foleds //DeleteNonexistentUsersAndGroups(rootPath); } #endregion #region Secured Helicon Ape Groups public override List GetHeliconApeGroups(string siteId) { string rootPath = GetSiteContentPath(siteId); List groups = new List(); // open groups file string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE); List groupLines = HtaccessFolder.ReadLinesFile(groupsPath); for (int i = 0; i < groupLines.Count; i++) { string groupLine = groupLines[i]; int colonIdx = groupLine.IndexOf(":"); if (colonIdx != -1) { string name = groupLine.Substring(0, colonIdx); // add group to the collection groups.Add(GetHeliconApeGroup(siteId, name)); } } // end iterating groups return groups; } public override WebGroup GetHeliconApeGroup(string siteId, string groupName) { string rootPath = GetSiteContentPath(siteId); // open groups file string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE); List groupLines = HtaccessFolder.ReadLinesFile(groupsPath); WebGroup group = null; for (int i = 0; i < groupLines.Count; i++) { string groupLine = groupLines[i]; int colonIdx = groupLine.IndexOf(":"); if (colonIdx != -1) { string name = groupLine.Substring(0, colonIdx); string[] members = groupLine.Substring(colonIdx + 1).Split(' '); if (String.Compare(groupName, name, true) == 0) { group = new WebGroup(); group.Name = groupName; group.Users = members; } } } // end iterating groups return group; } public override void UpdateHeliconApeGroup(string siteId, WebGroup group) { UpdateHeliconApeGroup(siteId, group, false); } private void UpdateHeliconApeGroup(string siteId, WebGroup group, bool deleteGroup) { string rootPath = GetSiteContentPath(siteId); if (group.Users == null) group.Users = new string[] { }; List updatedGroups = new List(); // open groups file string groupsPath = Path.Combine(rootPath, HtaccessFolder.HTGROUPS_FILE); List groupLines = HtaccessFolder.ReadLinesFile(groupsPath); bool exists = false; for (int i = 0; i < groupLines.Count; i++) { string groupLine = groupLines[i]; int colonIdx = groupLine.IndexOf(":"); if (colonIdx != -1) { string name = groupLine.Substring(0, colonIdx); // add group to the collection if (String.Compare(group.Name, name, true) == 0) { exists = true; if (deleteGroup) continue; // update group members groupLine = group.Name + ":" + String.Join(" ", group.Users); } } updatedGroups.Add(groupLine); } // end iterating groups if (!exists && !deleteGroup) updatedGroups.Add(group.Name + ":" + String.Join(" ", group.Users)); // save groups HtaccessFolder.WriteLinesFile(groupsPath, updatedGroups); } public override void DeleteHeliconApeGroup(string siteId, string groupName) { string rootPath = GetSiteContentPath(siteId); // delete group WebGroup group = new WebGroup(); group.Name = groupName; UpdateHeliconApeGroup(siteId, group, true); // update foleds //DeleteNonexistentUsersAndGroups(rootPath); } #endregion #region FrontPage public override bool IsFrontPageInstalled(string siteId) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { return IsFrontPageInstalled(srvman, siteId); } } private bool IsFrontPageInstalled(ServerManager srvman, string siteId) { // Get IIS web site id string m_webSiteId = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, "W3SVC/{0}"); // site port RegistryKey sitePortKey = Registry.LocalMachine.OpenSubKey(String.Format("{0}Port /LM/{1}:", FRONTPAGE_PORT_REGLOC, m_webSiteId)); if (sitePortKey == null) return false; // get required keys string keyAuthoring = (string)sitePortKey.GetValue("authoring"); string keyFrontPageRoot = (string)sitePortKey.GetValue("frontpageroot"); return (keyAuthoring != null && keyAuthoring.ToUpper() == "ENABLED" && keyFrontPageRoot != null && keyFrontPageRoot.IndexOf("\\50") != -1); } public override bool InstallFrontPage(string siteId, string username, string password) { // Ensure requested user account doesn't exist if (SecurityUtils.UserExists(username, ServerSettings, UsersOU)) return false; // Ensure a web site exists if (!SiteExists(siteId)) return false; // create user account SystemUser user = new SystemUser { Name = username, FullName = username, Description = "WebsitePanel System Account", Password = password, PasswordCantChange = true, PasswordNeverExpires = true, AccountDisabled = false, System = true, }; // create in the system SecurityUtils.CreateUser(user, ServerSettings, UsersOU, GroupsOU); try { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { string cmdPath = null; string cmdArgs = null; // string m_webSiteId = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, null); // try to install FPSE2002 // add registry key for anonymous group if not exists RegistryKey portsKey = Registry.LocalMachine.OpenSubKey(FRONTPAGE_ALLPORTS_REGLOC, true); portsKey.SetValue("anonusergroupprefix", "anonfp"); #region Create anonymous group to get FPSE work string groupName = "anonfp_" + m_webSiteId; if (!SecurityUtils.GroupExists(groupName, ServerSettings, GroupsOU)) { SystemGroup fpseGroup = new SystemGroup(); fpseGroup.Name = groupName; fpseGroup.Description = "Anonymous FPSE group for " + siteId + " web site"; fpseGroup.Members = new string[] { username }; SecurityUtils.CreateGroup(fpseGroup, ServerSettings, UsersOU, GroupsOU); } #endregion #region Install FPSE 2002 to the website by owsadm.exe install command cmdPath = Environment.ExpandEnvironmentVariables(FPSE2002_OWSADM_PATH); cmdArgs = String.Format("-o install -p /LM/W3SVC/{0} -u {1}", m_webSiteId, username); Log.WriteInfo("Command path: " + cmdPath); Log.WriteInfo("Command path: " + cmdArgs); Log.WriteInfo("FPSE2002 Install Log: " + FileUtils.ExecuteSystemCommand(cmdPath, cmdArgs)); #endregion } // Enable Windows Authentication mode winAuthSvc.SetEnabled(siteId, true); } catch (Exception ex) { Log.WriteError(ex); // Signal to the client installation request has been failed. return false; } return true; } public override void UninstallFrontPage(string siteId, string username) { using (ServerManager srvman = webObjectsSvc.GetServerManager()) { // Ensure a web site exists if (!webObjectsSvc.SiteExists(srvman, siteId)) return; try { string m_webSiteId = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, null); // remove anonymous group string groupName = "anonfp_" + m_webSiteId; if (SecurityUtils.GroupExists(groupName, ServerSettings, GroupsOU)) SecurityUtils.DeleteGroup(groupName, ServerSettings, GroupsOU); #region Trying to uninstall FPSE2002 from the web site // string cmdPath = null; string cmdArgs = null; cmdPath = Environment.ExpandEnvironmentVariables(FPSE2002_OWSADM_PATH); cmdArgs = String.Format("-o fulluninstall -p /LM/W3SVC/{0}", m_webSiteId); // launch system process Log.WriteInfo("FPSE2002 Uninstall Log: " + FileUtils.ExecuteSystemCommand(cmdPath, cmdArgs)); #endregion // delete user account if (SecurityUtils.UserExists(username, ServerSettings, UsersOU)) SecurityUtils.DeleteUser(username, ServerSettings, UsersOU); // Disable Windows Authentication mode winAuthSvc.SetEnabled(siteId, false); } catch (Exception ex) { Log.WriteError(String.Format("FPSE2002 uninstall error. Web site: {0}.", siteId), ex); } } } public override bool IsFrontPageSystemInstalled() { // we will lookup in the registry for the required information // check for FPSE 2002 RegistryKey keyFrontPage = Registry.LocalMachine.OpenSubKey(FRONTPAGE_2002_REGLOC); if (keyFrontPage == null) return false; string[] subKeys = keyFrontPage.GetSubKeyNames(); if (subKeys != null && subKeys.Length > 0) { foreach (string key in subKeys) { if (key == IIs60.FRONTPAGE_2002_INSTALLED || key == IIs60.SHAREPOINT_INSTALLED) return true; } } return false; } #endregion #region ColdFusion public override void CreateCFVirtualDirectories(string siteId) { WebVirtualDirectory scriptsDirectory = new WebVirtualDirectory(); scriptsDirectory.Name = "CFIDE"; scriptsDirectory.ContentPath = CFScriptsDirectoryPath; scriptsDirectory.EnableAnonymousAccess = true; scriptsDirectory.EnableWindowsAuthentication = true; scriptsDirectory.EnableBasicAuthentication = false; scriptsDirectory.DefaultDocs = null; // inherit from service scriptsDirectory.HttpRedirect = ""; scriptsDirectory.HttpErrors = null; scriptsDirectory.MimeMaps = null; if (!VirtualDirectoryExists(siteId, scriptsDirectory.Name)) { CreateVirtualDirectory(siteId, scriptsDirectory); } WebVirtualDirectory flashRemotingDir = new WebVirtualDirectory(); flashRemotingDir.Name = "JRunScripts"; flashRemotingDir.ContentPath = CFFlashRemotingDirPath; flashRemotingDir.EnableAnonymousAccess = true; flashRemotingDir.EnableWindowsAuthentication = true; flashRemotingDir.EnableBasicAuthentication = false; flashRemotingDir.DefaultDocs = null; // inherit from service flashRemotingDir.HttpRedirect = ""; flashRemotingDir.HttpErrors = null; flashRemotingDir.MimeMaps = null; if (!VirtualDirectoryExists(siteId, flashRemotingDir.Name)) { CreateVirtualDirectory(siteId, flashRemotingDir); } } public override void DeleteCFVirtualDirectories(string siteId) { DeleteVirtualDirectory(siteId, "CFIDE"); DeleteVirtualDirectory(siteId, "JRunScripts"); } public bool ColdFusionDirectoriesAdded(ServerManager srvman, string siteId) { int identifier = 0; WebVirtualDirectory[] dirs = GetVirtualDirectories(srvman, siteId); foreach (WebVirtualDirectory dir in dirs) { if (dir.FullQualifiedPath.Equals("CFIDE") || dir.FullQualifiedPath.Equals("JRunScripts")) identifier++; } return identifier.Equals(2); } protected override bool IsColdFusionEnabledOnSite(string siteId) { bool isCFenabled = false; using (ServerManager srvman = webObjectsSvc.GetServerManager()) { string ID = webObjectsSvc.GetWebSiteIdFromIIS(srvman, siteId, "{0}"); if (IsColdFusionSystemInstalled()) { string pathWsConfigSettings = Path.Combine(GetColdFusionRootPath(), @"runtime\lib\wsconfig\wsconfig.properties"); StreamReader file = new StreamReader(pathWsConfigSettings); string line = String.Empty; int counter = 0; while ((line = file.ReadLine()) != null) { if (line.Contains(String.Format("=IIS,{0},", ID))) { isCFenabled = true; break; } counter++; } file.Close(); } return isCFenabled; } } #endregion #region HostingServiceProvider methods public override SettingPair[] GetProviderDefaultSettings() { List allSettings = new List(); using (ServerManager srvman = webObjectsSvc.GetServerManager()) { allSettings.AddRange(extensionsSvc.GetISAPIExtensionsInstalled(srvman)); // add default web management settings WebManagementServiceSettings wmSettings = GetWebManagementServiceSettings(); if (wmSettings != null) { allSettings.Add(new SettingPair("WmSvc.Port", wmSettings.Port)); allSettings.Add(new SettingPair("WmSvc.ServiceUrl", wmSettings.ServiceUrl)); allSettings.Add(new SettingPair("WmSvc.RequiresWindowsCredentials", wmSettings.RequiresWindowsCredentials.ToString())); } } // return settings return allSettings.ToArray(); } /// /// Installs the provider. /// /// Error messsages if any specified. public override string[] Install() { List messages = new List(); string[] cfgMsgs = webObjectsSvc.GrantConfigurationSectionAccess(INSTALL_SECTIONS_ALLOWED); // if (cfgMsgs.Length > 0) { messages.AddRange(cfgMsgs); return messages.ToArray(); } try { SecurityUtils.EnsureOrganizationalUnitsExist(ServerSettings, UsersOU, GroupsOU); } catch (Exception ex) { Log.WriteError(ex); messages.Add(String.Format("Could not check/create Organizational Units: {0}", ex.Message)); return messages.ToArray(); } // Create web group name. if (String.IsNullOrEmpty(WebGroupName)) { messages.Add("Web Group can not be blank"); } else { try { // create group if (!SecurityUtils.GroupExists(WebGroupName, ServerSettings, GroupsOU)) { SystemGroup group = new SystemGroup(); group.Name = WebGroupName; group.Members = new string[] { }; group.Description = "WebsitePanel System Group"; SecurityUtils.CreateGroup(group, ServerSettings, UsersOU, GroupsOU); } } catch (Exception ex) { Log.WriteError(ex); messages.Add(String.Format("There was an error while adding '{0}' group: {1}", WebGroupName, ex.Message)); } } // Setting up shared iisAppObject pools. try { WebAppPoolHelper aphl = new WebAppPoolHelper(ProviderSettings); // Find shared pools var sharedPools = Array.FindAll(aphl.SupportedAppPools.ToArray(), x => aphl.isolation(x.Mode) == SiteAppPoolMode.Shared); // foreach (var item in sharedPools) { using (var srvman = webObjectsSvc.GetServerManager()) { // Local variables bool enable32BitAppOnWin64 = (aphl.dotNetVersion(item.Mode) == SiteAppPoolMode.dotNetFramework1) ? true : false; // if (srvman.ApplicationPools[item.Name] == null) { ApplicationPool pool = srvman.ApplicationPools.Add(item.Name); // pool.ManagedRuntimeVersion = aphl.aspnet_runtime(item.Mode); pool.ManagedPipelineMode = aphl.runtime_pipeline(item.Mode); pool.ProcessModel.IdentityType = ProcessModelIdentityType.NetworkService; pool.AutoStart = true; pool.Enable32BitAppOnWin64 = enable32BitAppOnWin64; // srvman.CommitChanges(); } } } } catch (Exception ex) { Log.WriteError(ex); // messages.Add(String.Format("There was an error while creating shared iisAppObject pools: {0}", ex.Message)); } // Ensure logging settings are configured correctly on a web server level try { webObjectsSvc.SetWebServerDefaultLoggingSettings(LogExtFileFlags.SiteName | LogExtFileFlags.BytesRecv | LogExtFileFlags.BytesSent | LogExtFileFlags.Date); } catch (Exception ex) { Log.WriteError(ex); // messages.Add(String.Format(@"There was an error while configure web server's default logging settings. Reason: {0}", ex.StackTrace)); } // Ensure logging settings are configured correctly on a web server level try { webObjectsSvc.SetWebServerDefaultLoggingSettings(LogExtFileFlags.SiteName | LogExtFileFlags.BytesRecv | LogExtFileFlags.BytesSent | LogExtFileFlags.Date); } catch (Exception ex) { Log.WriteError(ex); // messages.Add(String.Format(@"There was an error while configure web server's default logging settings. Reason: {0}", ex.StackTrace)); } // Setup Web Deploy publishing settings and rules SetupWebDeployPublishingOnServer(messages); return messages.ToArray(); } public const string WDeployEnabled = "WDeployEnabled"; public const string WDeployRepair = "WDeployRepair"; public const string WDeployAppHostConfigWriter = "WDeployAppHostConfigWriter"; public const string WDeployAppPoolConfigEditor = "WDeployAppPoolConfigEditor"; private void SetupWebDeployPublishingOnServer(List messages) { if (IsWebDeployInstalled() == false || String.IsNullOrEmpty(ProviderSettings[WDeployEnabled])) return; // var enableFeature = Convert.ToBoolean(ProviderSettings[WDeployEnabled]); var repairFeature = Convert.ToBoolean(ProviderSettings[WDeployRepair]); // var appHostConfigWriter = "WDeployConfigWriter"; var appHostConfigWriterPassword = Guid.NewGuid().ToString(); // var appPoolConfigEditor = "WDeployAdmin"; var appPoolConfigEditorPassword = Guid.NewGuid().ToString(); // var appHostConfigFilePath = FileUtils.EvaluateSystemVariables(@"%WINDIR%\system32\inetsrv\config\applicationHost.config"); // #region Repair feature if (repairFeature == true && enableFeature == true) { // Cleanup NTFS permissions SecurityUtils.RemoveNtfsPermissions(appHostConfigFilePath, appHostConfigWriter, ServerSettings, UsersOU, GroupsOU); // Remove applicationHost.config writer account SecurityUtils.DeleteUser(appHostConfigWriter, ServerSettings, UsersOU); // Remove local admin user to recycle app pools SecurityUtils.DeleteUser(appPoolConfigEditor, ServerSettings, UsersOU); // Remove delegation rules if any var moduleService = new DelegationRulesModuleService(); // moduleService.RemoveDelegationRule("contentPath,iisApp", "{userScope}"); moduleService.RemoveDelegationRule("dbFullSql", "Data Source="); moduleService.RemoveDelegationRule("dbMySql", "Server="); moduleService.RemoveDelegationRule("createApp", "{userScope}"); moduleService.RemoveDelegationRule("setAcl", "{userScope}"); moduleService.RemoveDelegationRule("recycleApp", "{userScope}"); moduleService.RemoveDelegationRule("appPoolPipeline,appPoolNetFx", "{userScope}"); } #endregion // Create applicationHost.config writer account #region appHostConfigWriter account provisioning if (enableFeature == true) { // if (SecurityUtils.UserExists(appHostConfigWriter, ServerSettings, UsersOU) == false) { // try { SecurityUtils.CreateUser(new SystemUser { Name = appHostConfigWriter, FullName = appHostConfigWriter, Password = appHostConfigWriterPassword, PasswordCantChange = true, PasswordNeverExpires = true, MemberOf = new string[] { }, Description = "Web Deploy applicationHost.config writer account", }, ServerSettings, UsersOU, GroupsOU); // Grant appropriate NTFS permissions SecurityUtils.GrantNtfsPermissions(appHostConfigFilePath, appHostConfigWriter, NTFSPermission.Modify, true, true, ServerSettings, UsersOU, GroupsOU); } catch (Exception ex) { var errorMessage = "Could not create applicationHost.config writer account"; // Log.WriteError(errorMessage, ex); // messages.Add(errorMessage); } } } else { if (SecurityUtils.UserExists(appHostConfigWriter, ServerSettings, UsersOU) == true) { // try { // Remove NTFS permissions SecurityUtils.RemoveNtfsPermissions(appHostConfigFilePath, appHostConfigWriter, ServerSettings, UsersOU, GroupsOU); // Remove writer account SecurityUtils.DeleteUser(appHostConfigWriter, ServerSettings, UsersOU); } catch (Exception ex) { var errorMessage = "Could not remove applicationHost.config writer user account"; // Log.WriteError(errorMessage, ex); // messages.Add(errorMessage); } } } #endregion // Create local admin user to recycle app pools #region appPoolConfigEditor account provisioning if (enableFeature) { // if (SecurityUtils.UserExists(appPoolConfigEditor, ServerSettings, UsersOU) == false) { // try { SecurityUtils.CreateUser(new SystemUser { Name = appPoolConfigEditor, FullName = appPoolConfigEditor, Password = appPoolConfigEditorPassword, PasswordCantChange = true, PasswordNeverExpires = true, MemberOf = new string[] { "Administrators" }, Description = "Web Deploy AppPool configuration editor account", }, ServerSettings, UsersOU, GroupsOU); } catch (Exception ex) { var errorMessage = "Could not create application pool configuration editor account"; // Log.WriteError(errorMessage, ex); // messages.Add(errorMessage); } } } else { if (SecurityUtils.UserExists(appPoolConfigEditor, ServerSettings, UsersOU) == true) { // try { // Remove appPool config editor account SecurityUtils.DeleteUser(appPoolConfigEditor, ServerSettings, UsersOU); } catch (Exception ex) { var errorMessage = "Could not remove applicationHost.config writer user account"; // Log.WriteError(errorMessage, ex); // messages.Add(errorMessage); } } } #endregion // Add delegation rules #region Delegation rules provisioning if (enableFeature) { var moduleService = new DelegationRulesModuleService(); // if (moduleService.DelegationRuleExists("contentPath,iisApp", "{userScope}") == false) { moduleService.AddDelegationRule("contentPath,iisApp", "{userScope}", "PathPrefix", "CurrentUser", String.Empty, String.Empty); } // if (moduleService.DelegationRuleExists("dbFullSql", "Data Source=") == false) { moduleService.AddDelegationRule("dbFullSql", "Data Source=", "ConnectionString", "CurrentUser", String.Empty, String.Empty); } // if (moduleService.DelegationRuleExists("dbMySql", "Server=") == false) { moduleService.AddDelegationRule("dbMySql", "Server=", "ConnectionString", "CurrentUser", String.Empty, String.Empty); } // if (moduleService.DelegationRuleExists("createApp", "{userScope}") == false) { moduleService.AddDelegationRule("createApp", "{userScope}", "PathPrefix", "SpecificUser", appHostConfigWriter, appHostConfigWriterPassword); } // if (moduleService.DelegationRuleExists("setAcl", "{userScope}") == false) { moduleService.AddDelegationRule("setAcl", "{userScope}", "PathPrefix", "CurrentUser", String.Empty, String.Empty); } // if (moduleService.DelegationRuleExists("recycleApp", "{userScope}") == false) { moduleService.AddDelegationRule("recycleApp", "{userScope}", "PathPrefix", "SpecificUser", appPoolConfigEditor, appPoolConfigEditorPassword); } // if (moduleService.DelegationRuleExists("appPoolPipeline,appPoolNetFx", "{userScope}") == false) { moduleService.AddDelegationRule("appPoolPipeline,appPoolNetFx", "{userScope}", "PathPrefix", "SpecificUser", appHostConfigWriter, appHostConfigWriterPassword); } } else { var moduleService = new DelegationRulesModuleService(); // moduleService.RemoveDelegationRule("contentPath,iisApp", "{userScope}"); moduleService.RemoveDelegationRule("dbFullSql", "Data Source="); moduleService.RemoveDelegationRule("dbMySql", "Server="); moduleService.RemoveDelegationRule("createApp", "{userScope}"); moduleService.RemoveDelegationRule("setAcl", "{userScope}"); moduleService.RemoveDelegationRule("recycleApp", "{userScope}"); moduleService.RemoveDelegationRule("appPoolPipeline,appPoolNetFx", "{userScope}"); } #endregion } public override ServiceProviderItemBandwidth[] GetServiceItemsBandwidth(ServiceProviderItem[] items, DateTime since) { ServiceProviderItemBandwidth[] itemsBandwidth = new ServiceProviderItemBandwidth[items.Length]; // update items with diskspace for (int i = 0; i < items.Length; i++) { ServiceProviderItem item = items[i]; // create new bandwidth object itemsBandwidth[i] = new ServiceProviderItemBandwidth(); itemsBandwidth[i].ItemId = item.Id; itemsBandwidth[i].Days = new DailyStatistics[0]; if (item is WebSite) { try { WebSite site = GetSite(item.Name); string siteId = site[WebSite.IIS7_SITE_ID]; string logsPath = Path.Combine(site.LogsPath, siteId); if (!Directory.Exists(logsPath)) continue; // create parser object // and update statistics LogParser parser = new LogParser("Web", siteId, logsPath, "s-sitename"); parser.ParseLogs(); // get daily statistics itemsBandwidth[i].Days = parser.GetDailyStatistics(since, new string[] { siteId }); } catch (Exception ex) { Log.WriteError(ex); } } } return itemsBandwidth; } public override ServiceProviderItemDiskSpace[] GetServiceItemsDiskSpace(ServiceProviderItem[] items) { List itemsDiskspace = new List(); // update items with diskspace foreach (ServiceProviderItem item in items) { if (item is WebSite) { try { Log.WriteStart(String.Format("Calculating '{0}' site logs size", item.Name)); WebSite site = GetSite(item.Name); // string logsPath = Path.Combine(site.LogsPath, site[WebSite.IIS7_SITE_ID]); // calculate disk space ServiceProviderItemDiskSpace diskspace = new ServiceProviderItemDiskSpace(); diskspace.ItemId = item.Id; diskspace.DiskSpace = -1 * FileUtils.CalculateFolderSize(logsPath); itemsDiskspace.Add(diskspace); Log.WriteEnd(String.Format("Calculating '{0}' site logs size", item.Name)); } catch (Exception ex) { Log.WriteError(ex); } } } return itemsDiskspace.ToArray(); } #endregion public new bool IsIISInstalled() { int value = 0; RegistryKey root = Registry.LocalMachine; RegistryKey rk = root.OpenSubKey("SOFTWARE\\Microsoft\\InetStp"); if (rk != null) { value = (int)rk.GetValue("MajorVersion", null); rk.Close(); } return value == 7; } public override bool IsInstalled() { return IsIISInstalled(); } #region Remote Management Access /// /// Provides Windows or IIS Management Users identities credentials mode /// public string IdentityCredentialsMode { get { return ProviderSettings["WmSvc.CredentialsMode"]; } } public override bool CheckWebManagementAccountExists(string accountName) { // Preserve setting to restore it back bool adEnabled = ServerSettings.ADEnabled; // !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user // against the web server //ServerSettings.ADEnabled = false; if (IdentityCredentialsMode == "IISMNGR") { if (ManagementAuthentication.GetUser(accountName) != null) return true; else return false; } else { return SecurityUtils.UserExists(accountName, ServerSettings, String.Empty); } } public override ResultObject CheckWebManagementPasswordComplexity(string accountPassword) { // Preserve setting to restore it back bool adEnabled = ServerSettings.ADEnabled; // !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user // against the web server //ServerSettings.ADEnabled = false; // ResultObject result = new ResultObject { IsSuccess = true }; // if (IdentityCredentialsMode == "IISMNGR") { InvalidPasswordReason reason = ManagementAuthentication.IsPasswordStrongEnough(accountPassword); // if (reason != InvalidPasswordReason.NoError) { result.IsSuccess = false; result.AddError(reason.ToString(), new Exception("Password complexity check failed")); } } // Restore setting back ServerSettings.ADEnabled = adEnabled; // return result; } public override void GrantWebManagementAccess(string siteName, string accountName, string accountPassword) { // Remote Management Access feature requires Modify permissions on the web site's wwwroot folder GrantWebManagementAccessInternally(siteName, accountName, accountPassword, NTFSPermission.Modify); } private void GrantWebManagementAccessInternally(string siteName, string accountName, string accountPassword, NTFSPermission permissions) { // Preserve setting to restore it back bool adEnabled = ServerSettings.ADEnabled; // !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user // against the web server //ServerSettings.ADEnabled = false; // string fqWebPath = String.Format("/{0}", siteName); // Trace input parameters Log.WriteInfo("Site Name: {0}; Account Name: {1}; Account Password: {2}; FqWebPath: {3};", siteName, accountName, accountPassword, fqWebPath); string contentPath = string.Empty; using (ServerManager srvman = webObjectsSvc.GetServerManager()) { WebSite site = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName); // contentPath = webObjectsSvc.GetPhysicalPath(srvman, site); // Log.WriteInfo("Site Content Path: {0};", contentPath); } string FTPRoot = string.Empty; string FTPDir = string.Empty; if (contentPath.IndexOf("\\\\") != -1) { string[] Tmp = contentPath.Split('\\'); FTPRoot = "\\\\" + Tmp[2] + "\\" + Tmp[3]; FTPDir = contentPath.Replace(FTPRoot, ""); } // string accountNameSid = string.Empty; // if (IdentityCredentialsMode == "IISMNGR") { ManagementAuthentication.CreateUser(accountName, accountPassword); } else { // Create Windows user SecurityUtils.CreateUser( new SystemUser { Name = accountName, FullName = accountName, Description = "WMSVC Service Account created by WebsitePanel", PasswordCantChange = true, PasswordNeverExpires = true, AccountDisabled = false, Password = accountPassword, System = true, MsIIS_FTPDir = FTPDir, MsIIS_FTPRoot = FTPRoot }, ServerSettings, UsersOU, GroupsOU); // Convert account name to the full-qualified one accountName = GetFullQualifiedAccountName(accountName); accountNameSid = GetFullQualifiedAccountNameSid(accountName); // Log.WriteInfo("FQ Account Name: {0};", accountName); } ManagementAuthorization.Grant(accountName, fqWebPath, false); // if (IdentityCredentialsMode == "IISMNGR") { SecurityUtils.GrantNtfsPermissionsBySid(contentPath, SystemSID.LOCAL_SERVICE, permissions, true, true); } else { SecurityUtils.GrantNtfsPermissions(contentPath, accountNameSid, NTFSPermission.Modify, true, true, ServerSettings, UsersOU, GroupsOU); } } public override void ChangeWebManagementAccessPassword(string accountName, string accountPassword) { // Preserve setting to restore it back bool adEnabled = ServerSettings.ADEnabled; // !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user // against the web server //ServerSettings.ADEnabled = false; // Trace input parameters Log.WriteInfo("Account Name: {0}; Account Password: {1};", accountName, accountPassword); if (IdentityCredentialsMode == "IISMNGR") { ManagementAuthentication.SetPassword(accountName, accountPassword); } else { // SystemUser user = SecurityUtils.GetUser(accountName, ServerSettings, String.Empty); // user.Password = accountPassword; // SecurityUtils.UpdateUser(user, ServerSettings, String.Empty, String.Empty); } // Restore setting back ServerSettings.ADEnabled = adEnabled; } public override void RevokeWebManagementAccess(string siteName, string accountName) { // Preserve setting to restore it back bool adEnabled = ServerSettings.ADEnabled; // !!! Bypass AD for WMSVC as it requires full-qualified username to authenticate user // against the web server //ServerSettings.ADEnabled = false; // string fqWebPath = String.Format("/{0}", siteName); // Trace input parameters Log.WriteInfo("Site Name: {0}; Account Name: {1}; FqWebPath: {2};", siteName, accountName, fqWebPath); using (ServerManager srvman = webObjectsSvc.GetServerManager()) { // WebSite site = webObjectsSvc.GetWebSiteFromIIS(srvman, siteName); // string contentPath = webObjectsSvc.GetPhysicalPath(srvman, site); // Log.WriteInfo("Site Content Path: {0};", contentPath); // Revoke access permissions if (IdentityCredentialsMode == "IISMNGR") { ManagementAuthorization.Revoke(accountName, fqWebPath); ManagementAuthentication.DeleteUser(accountName); SecurityUtils.RemoveNtfsPermissionsBySid(contentPath, SystemSID.LOCAL_SERVICE); } else { if (adEnabled) { ManagementAuthorization.Revoke(GetFullQualifiedAccountName(accountName), fqWebPath); SecurityUtils.RemoveNtfsPermissions(contentPath, accountName, ServerSettings, UsersOU, GroupsOU); SecurityUtils.DeleteUser(accountName, ServerSettings, UsersOU); } else { ManagementAuthorization.Revoke(GetFullQualifiedAccountName(accountName), fqWebPath); SecurityUtils.RemoveNtfsPermissions(contentPath, accountName, ServerSettings, String.Empty, String.Empty); SecurityUtils.DeleteUser(accountName, ServerSettings, String.Empty); } } // Restore setting back ServerSettings.ADEnabled = adEnabled; } } private void ReadWebDeployPublishingAccessDetails(WebVirtualDirectory iisObject) { iisObject.WebDeployPublishingAvailable = IsWebDeployInstalled() && IsWebManagementServiceInstalled(); // No way to find out Web Deploy Publishing Access password //iisObject. } private bool IsWebDeployInstalled() { // TO-DO: Implement Web Deploy detection (x64/x86) var isInstalled = false; // try { var msdeployRegKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\IIS Extensions\MSDeploy\2"); // var keyValue = msdeployRegKey.GetValue("Install"); // We have found the required key in the registry hive if (keyValue != null && keyValue.Equals(1)) { isInstalled = true; } } catch (Exception ex) { Log.WriteError("Could not retrieve Web Deploy key from the registry", ex); } // return isInstalled; } private bool? isWmSvcInstalled; protected void ReadWebManagementAccessDetails(ServerManager srvman, WebVirtualDirectory iisObject) { bool wmSvcAvailable = IsWebManagementServiceInstalled(); // iisObject.SetValue(WebSite.WmSvcAvailable, wmSvcAvailable); // if (wmSvcAvailable) { // iisObject.SetValue( WebVirtualDirectory.WmSvcSiteEnabled, IsWebManagementAccessEnabled(iisObject)); // string fqWebPath = @"/" + iisObject.FullQualifiedPath; // Configuration config = srvman.GetAdministrationConfiguration(); ConfigurationSection authorizationSection = config.GetSection("system.webServer/management/authorization"); ConfigurationElementCollection authorizationRulesCollection = authorizationSection.GetCollection("authorizationRules"); ConfigurationElement scopeElement = FindElement(authorizationRulesCollection, "scope", "path", fqWebPath); Log.WriteInfo("FQ WebPath: " + fqWebPath); if (scopeElement != null) { ConfigurationElementCollection scopeCollection = scopeElement.GetCollection(); // Retrieve account name if (scopeCollection.Count > 0) { /* iisObject.SetValue( WebSite.WmSvcAccountName, GetNonQualifiedAccountName((String)scopeCollection[0]["name"])); */ iisObject.SetValue( WebSite.WmSvcAccountName, (String)scopeCollection[0]["name"]); // iisObject.SetValue( WebSite.WmSvcServiceUrl, ProviderSettings["WmSvc.ServiceUrl"]); // iisObject.SetValue( WebSite.WmSvcServicePort, ProviderSettings["WmSvc.Port"]); } } } } protected ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues) { foreach (ConfigurationElement element in collection) { if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase)) { bool matches = true; for (int i = 0; i < keyValues.Length; i += 2) { object o = element.GetAttributeValue(keyValues[i]); string value = null; if (o != null) { value = o.ToString(); } if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase)) { matches = false; break; } } if (matches) { return element; } } } return null; } private bool IsWebManagementAccessEnabled(WebVirtualDirectory iisObject) { using (var serverManager = webObjectsSvc.GetServerManager()) { // string fqWebPath = String.Format("/{0}", iisObject.FullQualifiedPath); // Log.WriteInfo("FQ Web Path: " + fqWebPath); // Configuration config = serverManager.GetAdministrationConfiguration(); ConfigurationSection authorizationSection = config.GetSection("system.webServer/management/authorization"); ConfigurationElementCollection authorizationRulesCollection = authorizationSection.GetCollection("authorizationRules"); ConfigurationElement scopeElement = FindElement(authorizationRulesCollection, "scope", "path", fqWebPath); if (scopeElement != null) { // At least one authorization rule exists if (scopeElement.GetCollection().Count > 0) { return true; } } } // return false; } private bool IsWebManagementServiceInstalled() { if (!isWmSvcInstalled.HasValue) { try { // Software key has been found, so report the check as succeeded if (PInvoke.RegistryHive.HKLM.SubKeyExists_x64(@"SOFTWARE\Microsoft\WebManagement\Server")) { // Make sure Enable Remote Connections flag is turned on. int remoteConnEnabled = PInvoke.RegistryHive.HKLM.GetDwordSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server", "EnableRemoteManagement"); // if (remoteConnEnabled == 1) isWmSvcInstalled = true; } else isWmSvcInstalled = false; } catch (Exception ex) { Log.WriteError("Failed to determine whether Web Management Service is installed", ex); } } // Service not installed return isWmSvcInstalled.GetValueOrDefault(); } protected WebManagementServiceSettings GetWebManagementServiceSettings() { WebManagementServiceSettings settings = null; try { // Trying to retrieve Web Management Server key if (PInvoke.RegistryHive.HKLM.SubKeyExists_x64(@"SOFTWARE\Microsoft\WebManagement\Server")) { settings = new WebManagementServiceSettings(); // port number settings.Port = PInvoke.RegistryHive.HKLM.GetDwordSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server", "Port").ToString(); // service URL settings.ServiceUrl = PInvoke.RegistryHive.HKLM.GetSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server", "IPAddress"); // credentials mode settings.RequiresWindowsCredentials = PInvoke.RegistryHive.HKLM.GetDwordSubKeyValue_x64(@"SOFTWARE\Microsoft\WebManagement\Server", "RequiresWindowsCredentials"); } } catch (Exception ex) { Log.WriteError("Failed to retrieve Web Management Service settings", ex); } // return settings; } protected string GetFullQualifiedAccountName(string accountName) { // if (!ServerSettings.ADEnabled) return String.Format(@"{0}\{1}", Environment.MachineName, accountName); if (accountName.IndexOf("\\") != -1) return accountName; // already has domain information // DO IT FOR ACTIVE DIRECTORY MODE ONLY string domainName = null; try { DirectoryContext objContext = new DirectoryContext(DirectoryContextType.Domain, ServerSettings.ADRootDomain); Domain objDomain = Domain.GetDomain(objContext); domainName = objDomain.Name; } catch (Exception ex) { Log.WriteError("Get domain name error", ex); } return domainName != null ? domainName + "\\" + accountName : accountName; } protected string GetFullQualifiedAccountNameSid(string accountName) { // if (!ServerSettings.ADEnabled) return String.Format(@"{0}\{1}", Environment.MachineName, accountName); if (accountName.IndexOf("\\") != -1) return accountName; // already has domain information // DO IT FOR ACTIVE DIRECTORY MODE ONLY string domainName = null; try { DirectoryContext objContext = new DirectoryContext(DirectoryContextType.Domain, ServerSettings.ADRootDomain); Domain objDomain = Domain.GetDomain(objContext); domainName = objDomain.Name; } catch (Exception ex) { Log.WriteError("Get domain name error", ex); } return domainName != null ? domainName + "\\" + accountName : accountName; } #endregion #region SSL public override SSLCertificate generateCSR(SSLCertificate certificate) { var sslObjectService = new SSLModuleService(); // sslObjectService.GenerateCsr(certificate); return certificate; } public override SSLCertificate installCertificate(SSLCertificate certificate, WebSite website) { var sslObjectService = new SSLModuleService(); // return sslObjectService.InstallCertificate(certificate, website); } public override List getServerCertificates() { var sslObjectService = new SSLModuleService(); // return sslObjectService.GetServerCertificates(); } public override SSLCertificate installPFX(byte[] certificate, string password, WebSite website) { var sslObjectService = new SSLModuleService(); // return sslObjectService.InstallPfx(certificate, password, website); } public override byte[] exportCertificate(string serialNumber, string password) { var sslObjectService = new SSLModuleService(); // return sslObjectService.ExportPfx(serialNumber, password); } public override ResultObject DeleteCertificate(SSLCertificate certificate, WebSite website) { var sslObjectService = new SSLModuleService(); // return sslObjectService.DeleteCertificate(certificate, website); } public override SSLCertificate ImportCertificate(WebSite website) { var sslObjectService = new SSLModuleService(); // return sslObjectService.ImportCertificate(website); } public override bool CheckCertificate(WebSite webSite) { var sslObjectService = new SSLModuleService(); // return sslObjectService.CheckCertificate(webSite); } #endregion #region Web Platform Installer Application Gallery // moved down to IIs60 #endregion } }