<commit_before>﻿using Autofac;
using LetsEncrypt.ACME.Simple.Services;
using Microsoft.Web.Administration;
using Microsoft.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace LetsEncrypt.ACME.Simple.Clients
{
    public class IISClient
    {
        private const string _anonymousAuthenticationSection = "system.webServer/security/authentication/anonymousAuthentication";
        private const string _accessSecuritySection = "system.webServer/security/access";
        private const string _handlerSection = "system.webServer/handlers";
        private const string _ipSecuritySection = "system.webServer/security/ipSecurity";
        private const string _urlRewriteSection = "system.webServer/rewrite/rules";
        private const string _modulesSection = "system.webServer/modules";

        public static Version Version = GetIISVersion();
        private bool RewriteModule = GetRewriteModulePresent();
        public IdnMapping IdnMapping = new IdnMapping();
        protected ILogService _log;

        [Flags]
        public enum SSLFlags
        {
            SNI = 1,
            CentralSSL = 2
        }

        public IISClient(ILogService log)
        {
            _log = log;
        }

        public ServerManager ServerManager
        {
            get
            {
                if (_ServerManager == null)
                {
                    if (Version.Major > 0)
                    {
                        _ServerManager = new ServerManager();
                    }
                }
                return _ServerManager;
            }
        }

        /// <summary>
        /// Commit changes to server manager and remove the 
        /// reference to the cached version because it might
        /// be the cause of some bug to keep using the same
        /// ServerManager to commit multiple changes
        /// </summary>
        public void Commit()
        {
            if (_ServerManager != null)
            {
                _ServerManager.CommitChanges();
                _ServerManager = null;
            }
        }

        private ServerManager _ServerManager;


        public IEnumerable<Site> RunningWebsites()
        {
            return ServerManager.Sites.AsEnumerable().
                Where(s => s.Bindings.Any(sb => sb.Protocol == "http" || sb.Protocol == "https")).
                Where(s => s.State == ObjectState.Started).
                OrderBy(s => s.Name);
        }
            
        /// <summary>
        /// Configures the site for ACME validation without generating an overly complicated web.config
        /// </summary>
        /// <param name="target"></param>
        public void PrepareSite(Target target)
        {
            var config = ServerManager.GetApplicationHostConfiguration();
            var site = GetSite(target);

            // Only do it for the .well-known folder, do not compromise security for other parts of the application
            var wellKnown = "/.well-known";
            var parentPath = site.Name;
            var path = parentPath + wellKnown;

            // Create application
            var rootApp = site.Applications.FirstOrDefault(x => x.Path == "/");
            var rootVdir = rootApp.VirtualDirectories.FirstOrDefault(x => x.Path == "/");
            var leApp = site.Applications.FirstOrDefault(a => a.Path == wellKnown);
            var leVdir = leApp?.VirtualDirectories.FirstOrDefault(v => v.Path == "/");
            if (leApp == null)
            {
                leApp = site.Applications.CreateElement();
                leApp.ApplicationPoolName = rootApp.ApplicationPoolName;
                leApp.Path = wellKnown;
                site.Applications.Add(leApp);
            }
            if (leVdir == null)
            {
                leVdir = leApp.VirtualDirectories.CreateElement();
                leVdir.Path = "/";
                leApp.VirtualDirectories.Add(leVdir);
            }
            leVdir.PhysicalPath = rootVdir.PhysicalPath.TrimEnd('\\') + "\\.well-known\\";

            // Enabled Anonymous authentication
            ConfigurationSection anonymousAuthenticationSection = config.GetSection(_anonymousAuthenticationSection, path);
            anonymousAuthenticationSection["enabled"] = true;

            // Disable "Require SSL"
            ConfigurationSection accessSecuritySection = config.GetSection(_accessSecuritySection, path);
            accessSecuritySection["sslFlags"] = "None";

            // Disable IP restrictions
            ConfigurationSection ipSecuritySection = config.GetSection(_ipSecuritySection, path);
            ipSecuritySection["allowUnlisted"] = true;

            ConfigurationSection globalModules = config.GetSection(_modulesSection);
            ConfigurationSection parentModules = config.GetSection(_modulesSection, parentPath);
            ConfigurationSection modulesSection = config.GetSection(_modulesSection, path);
            ConfigurationElementCollection modulesCollection = modulesSection.GetCollection();
            modulesSection["runAllManagedModulesForAllRequests"] = false;
            var globals = globalModules.GetCollection().Select(gm => gm.GetAttributeValue("name")).ToList();
            foreach (var module in parentModules.GetCollection())
            {
                var moduleName = module.GetAttributeValue("name");
                if (!globals.Contains(moduleName))
                {
                    ConfigurationElement newModule = modulesCollection.CreateElement("remove");
                    newModule.SetAttributeValue("name", moduleName);
                    modulesCollection.Add(newModule);
                }
            }

            // Configure handlers
            ConfigurationSection handlerSection = config.GetSection(_handlerSection, path);
            ConfigurationElementCollection handlersCollection = handlerSection.GetCollection();
            handlersCollection.Clear();
            ConfigurationElement addElement = handlersCollection.CreateElement("add");<commit_msg>prevent double remove<commit_after>﻿using Autofac;
using LetsEncrypt.ACME.Simple.Services;
using Microsoft.Web.Administration;
using Microsoft.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace LetsEncrypt.ACME.Simple.Clients
{
    public class IISClient
    {
        private const string _anonymousAuthenticationSection = "system.webServer/security/authentication/anonymousAuthentication";
        private const string _accessSecuritySection = "system.webServer/security/access";
        private const string _handlerSection = "system.webServer/handlers";
        private const string _ipSecuritySection = "system.webServer/security/ipSecurity";
        private const string _urlRewriteSection = "system.webServer/rewrite/rules";
        private const string _modulesSection = "system.webServer/modules";

        public static Version Version = GetIISVersion();
        private bool RewriteModule = GetRewriteModulePresent();
        public IdnMapping IdnMapping = new IdnMapping();
        protected ILogService _log;

        [Flags]
        public enum SSLFlags
        {
            SNI = 1,
            CentralSSL = 2
        }

        public IISClient(ILogService log)
        {
            _log = log;
        }

        public ServerManager ServerManager
        {
            get
            {
                if (_ServerManager == null)
                {
                    if (Version.Major > 0)
                    {
                        _ServerManager = new ServerManager();
                    }
                }
                return _ServerManager;
            }
        }

        /// <summary>
        /// Commit changes to server manager and remove the 
        /// reference to the cached version because it might
        /// be the cause of some bug to keep using the same
        /// ServerManager to commit multiple changes
        /// </summary>
        public void Commit()
        {
            if (_ServerManager != null)
            {
                _ServerManager.CommitChanges();
                _ServerManager = null;
            }
        }

        private ServerManager _ServerManager;


        public IEnumerable<Site> RunningWebsites()
        {
            return ServerManager.Sites.AsEnumerable().
                Where(s => s.Bindings.Any(sb => sb.Protocol == "http" || sb.Protocol == "https")).
                Where(s => s.State == ObjectState.Started).
                OrderBy(s => s.Name);
        }
            
        /// <summary>
        /// Configures the site for ACME validation without generating an overly complicated web.config
        /// </summary>
        /// <param name="target"></param>
        public void PrepareSite(Target target)
        {
            var config = ServerManager.GetApplicationHostConfiguration();
            var site = GetSite(target);

            // Only do it for the .well-known folder, do not compromise security for other parts of the application
            var wellKnown = "/.well-known";
            var parentPath = site.Name;
            var path = parentPath + wellKnown;

            // Create application
            var rootApp = site.Applications.FirstOrDefault(x => x.Path == "/");
            var rootVdir = rootApp.VirtualDirectories.FirstOrDefault(x => x.Path == "/");
            var leApp = site.Applications.FirstOrDefault(a => a.Path == wellKnown);
            var leVdir = leApp?.VirtualDirectories.FirstOrDefault(v => v.Path == "/");
            if (leApp == null)
            {
                leApp = site.Applications.CreateElement();
                leApp.ApplicationPoolName = rootApp.ApplicationPoolName;
                leApp.Path = wellKnown;
                site.Applications.Add(leApp);
            }
            if (leVdir == null)
            {
                leVdir = leApp.VirtualDirectories.CreateElement();
                leVdir.Path = "/";
                leApp.VirtualDirectories.Add(leVdir);
            }
            leVdir.PhysicalPath = rootVdir.PhysicalPath.TrimEnd('\\') + "\\.well-known\\";

            // Enabled Anonymous authentication
            ConfigurationSection anonymousAuthenticationSection = config.GetSection(_anonymousAuthenticationSection, path);
            anonymousAuthenticationSection["enabled"] = true;

            // Disable "Require SSL"
            ConfigurationSection accessSecuritySection = config.GetSection(_accessSecuritySection, path);
            accessSecuritySection["sslFlags"] = "None";

            // Disable IP restrictions
            ConfigurationSection ipSecuritySection = config.GetSection(_ipSecuritySection, path);
            ipSecuritySection["allowUnlisted"] = true;

            ConfigurationSection globalModules = config.GetSection(_modulesSection);
            ConfigurationSection parentModules = config.GetSection(_modulesSection, parentPath);
            ConfigurationSection modulesSection = config.GetSection(_modulesSection, path);
            ConfigurationElementCollection modulesCollection = modulesSection.GetCollection();
            modulesSection["runAllManagedModulesForAllRequests"] = false;
            var globals = globalModules.GetCollection().Select(gm => gm.GetAttributeValue("name")).ToList();
            var locals = modulesCollection.Select(gm => gm.GetAttributeValue("name")).ToList();
            foreach (var module in parentModules.GetCollection())
            {
                var moduleName = module.GetAttributeValue("name");
                if (!globals.Contains(moduleName) && locals.Contains(moduleName))
                {
                    ConfigurationElement newModule = modulesCollection.CreateElement("remove");
                    newModule.SetAttributeValue("name", moduleName);
                    modulesCollection.Add(newModule);
                }
            }

            // Configure handlers
            ConfigurationSection handlerSection = config.GetSection(_handlerSection, path);
            ConfigurationElementCollection handlersCollection = handlerSection.GetCollection();
            handlersCollection.Clear();
            ConfigurationElement addElement = handlersCollection.CreateElement("add");
{'fraction_non_alphanumeric': 0.08910811029352309, 'fraction_numerical': 0.0008086035416835126, 'mean_word_length': 2.0261805725471005, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1448988', 'n_tokens_mistral': 2911, 'n_tokens_neox': 2779, 'n_words': 662}