<commit_before>﻿/*
	Copyright (c) 2012, pGina Team
	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 pGina Team 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.ServiceProcess;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Reflection;
using Microsoft.Win32;

using log4net;
using System.Configuration.Install;

namespace pGina.InstallUtil
{
    class Program
    {
        static readonly string PGINA_SERVICE_NAME = "pGina";
        static readonly string PGINA_SERVICE_EXE = "pGina.Service.ServiceHost.exe";
        static readonly string PGINA_CONFIG_EXE = "pGina.Configuration.exe";
        
        // Initalized in the static constructor
        static readonly SecurityIdentifier ADMIN_GROUP;
        static readonly SecurityIdentifier USERS_GROUP;
        static readonly SecurityIdentifier SYSTEM_ACCT;
        static readonly SecurityIdentifier AUTHED_USERS;
        private static readonly string INSTALL_UTIL_PATH;
        private static readonly string PGINA_SERVICE_FULL_PATH;
        
        static Program()
        {
            // Init logging
            pGina.Shared.Logging.Logging.Init();
            
            // Intialize readonly variables

            PGINA_SERVICE_FULL_PATH = Path.Combine(
               Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), PGINA_SERVICE_EXE);
            INSTALL_UTIL_PATH = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(),
                "installutil.exe");

            ADMIN_GROUP = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
            USERS_GROUP = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
            SYSTEM_ACCT = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
            AUTHED_USERS = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
        }

        static ILog m_logger = LogManager.GetLogger("pGina.InstallUtil");

        static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                m_logger.Error("Missing argument.  Must be one of \"post-install\" or \"post-uninstall\".");
                return 1;
            }

            try
            {
                if (args[0].Equals("post-install", StringComparison.CurrentCultureIgnoreCase))
                {
                    DoPostInstall();
                }
                else if (args[0].Equals("post-uninstall", StringComparison.CurrentCultureIgnoreCase))
                {
                    DoPostUninstall();
                }
                else
                {
                    m_logger.ErrorFormat("Unrecognzied action: {0}", args[0]);
                    return 1;
                }
            }
            catch (Exception e)
            {
                m_logger.ErrorFormat("Exception occured: {0}", e);
                return 1;
            }

            return 0;
        }

        private static void DoPostInstall()
        {
            SetRegistryAcls();
            InstallAndStartService();
            RegisterAndEnableCredentialProvider();

            // Probably not necessary or useful...
            //SetFileSystemAcls();
        }

        private static void DoPostUninstall()
        {
            // Uninstall service
            if (ServiceInstalled())
            {
                StopService();
                UninstallService();
            }
            else
            {
                m_logger.Info("pGina service is not installed, skipping uninstall.");
            }

            // Uninstall CP
            UninstallCredentialProvider();
        }

        private static void SetFileSystemAcls()
        {
            if (!File.Exists(PGINA_CONFIG_EXE))
            {
                throw new Exception(string.Format("Unable to find configuration executable: {0}", PGINA_CONFIG_EXE));
            }

            m_logger.InfoFormat("Setting ACLs on {0}", PGINA_CONFIG_EXE);

            FileSystemAccessRule userReadAndExecute = new FileSystemAccessRule(USERS_GROUP, FileSystemRights.ReadAndExecute, AccessControlType.Allow);
            FileSystemAccessRule userRead = new FileSystemAccessRule(USERS_GROUP, FileSystemRights.Read, AccessControlType.Allow);
            FileSystemAccessRule adminFull = new FileSystemAccessRule(ADMIN_GROUP, FileSystemRights.FullControl, AccessControlType.Allow);
            FileSystemAccessRule systemFull = new FileSystemAccessRule(SYSTEM_ACCT, FileSystemRights.FullControl, AccessControlType.Allow);
            FileSystemAccessRule authedUsersMod = new FileSystemAccessRule(AUTHED_USERS, FileSystemRights.Modify, AccessControlType.Allow);
            FileSystemAccessRule usersMod = new FileSystemAccessRule(USERS_GROUP, FileSystemRights.Modify, AccessControlType.Allow);
            FileSecurity fs = File.GetAccessControl(PGINA_CONFIG_EXE);

            fs.SetAccessRuleProtection(true, false);

            fs.RemoveAccessRuleAll(authedUsersMod);
            fs.RemoveAccessRuleAll(usersMod);
            fs.AddAccessRule(userReadAndExecute);
            fs.AddAccessRule(adminFull);
            fs.AddAccessRule(systemFull);

            File.SetAccessControl(PGINA_CONFIG_EXE, fs);
        }

        private static void SetRegistryAcls()
        {
            string pGinaSubKey = pGina.Shared.Settings.pGinaDynamicSettings.pGinaRoot;

            using (RegistryKey key = Registry.LocalMachine.CreateSubKey(pGinaSubKey))
            {
                if (key != null)
                {
                    m_logger.InfoFormat("Setting ACLs on {0}", key.Name);

                    RegistryAccessRule allowRead = new RegistryAccessRule(<commit_msg>Install util updates the plugin path if it is set to the default for 3.1.6 and earlier.   - Remove some unused code.<commit_after>﻿/*
	Copyright (c) 2012, pGina Team
	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 pGina Team 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.ServiceProcess;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Reflection;
using Microsoft.Win32;

using log4net;
using System.Configuration.Install;

namespace pGina.InstallUtil
{
    class Program
    {
        static readonly string PGINA_SERVICE_NAME = "pGina";
        static readonly string PGINA_SERVICE_EXE = "pGina.Service.ServiceHost.exe";
        
        // Initalized in the static constructor
        static readonly SecurityIdentifier ADMIN_GROUP;
        static readonly SecurityIdentifier USERS_GROUP;
        static readonly SecurityIdentifier SYSTEM_ACCT;
        static readonly SecurityIdentifier AUTHED_USERS;
        private static readonly string INSTALL_UTIL_PATH;
        private static readonly string PGINA_SERVICE_FULL_PATH;
        
        static Program()
        {
            // Init logging
            pGina.Shared.Logging.Logging.Init();
            
            // Intialize readonly variables

            PGINA_SERVICE_FULL_PATH = Path.Combine(
               Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), PGINA_SERVICE_EXE);
            INSTALL_UTIL_PATH = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(),
                "installutil.exe");

            ADMIN_GROUP = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
            USERS_GROUP = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
            SYSTEM_ACCT = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
            AUTHED_USERS = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
        }

        static ILog m_logger = LogManager.GetLogger("pGina.InstallUtil");

        static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                m_logger.Error("Missing argument.  Must be one of \"post-install\" or \"post-uninstall\".");
                return 1;
            }

            try
            {
                if (args[0].Equals("post-install", StringComparison.CurrentCultureIgnoreCase))
                {
                    DoPostInstall();
                }
                else if (args[0].Equals("post-uninstall", StringComparison.CurrentCultureIgnoreCase))
                {
                    DoPostUninstall();
                }
                else
                {
                    m_logger.ErrorFormat("Unrecognzied action: {0}", args[0]);
                    return 1;
                }
            }
            catch (Exception e)
            {
                m_logger.ErrorFormat("Exception occured: {0}", e);
                return 1;
            }

            return 0;
        }

        private static void DoPostInstall()
        {
            SetRegistryAcls();
            InstallAndStartService();
            RegisterAndEnableCredentialProvider();
            UpdatePluginPath();
        }

        /// <summary>
        /// If the current plugin path is the default for pGina 3.1.6 and earlier, 
        /// update it for later versions.
        /// </summary>
        private static void UpdatePluginPath()
        {
            m_logger.Debug("Checking plugin path to see if it needs to be updated.");
            string pluginsBaseDir = 
                string.Format( @"{0}\Plugins",
                    Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

            dynamic settings = new pGina.Shared.Settings.pGinaDynamicSettings();
            string[] pluginDirs = settings.PluginDirectories;
            if (pluginDirs.Length == 1 &&
                pluginDirs[0].Equals(pluginsBaseDir, StringComparison.CurrentCultureIgnoreCase))
            {
                m_logger.Info("Updating plugin path for core/contrib subdirectories.");
                settings.PluginDirectories = new string[] { 
                    string.Format(@"{0}\Core", pluginsBaseDir),
                    string.Format(@"{0}\Contrib", pluginsBaseDir)
                };
            }
        }

        private static void DoPostUninstall()
        {
            // Uninstall service
            if (ServiceInstalled())
            {
                StopService();
                UninstallService();
            }
            else
            {
                m_logger.Info("pGina service is not installed, skipping uninstall.");
            }

            // Uninstall CP
            UninstallCredentialProvider();
        }

        private static void SetRegistryAcls()
        {
            string pGinaSubKey = pGina.Shared.Settings.pGinaDynamicSettings.pGinaRoot;

            using (RegistryKey key = Registry.LocalMachine.CreateSubKey(pGinaSubKey))
            {
                if (key != null)
                {
                    m_logger.InfoFormat("Setting ACLs on {0}", key.Name);

                    RegistryAccessRule allowRead = new RegistryAccessRule(
{'fraction_non_alphanumeric': 0.06907682375726275, 'fraction_numerical': 0.003514812423785955, 'mean_word_length': 2.27046680741262, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '3850476', 'n_tokens_mistral': 3621, 'n_tokens_neox': 3346, 'n_words': 1014}