/// <summary> /// Loads all persisted Prison instances. /// <remarks> /// This method assumes that serialized Prison objects are stored in a folder named 'db', next to the assembly. /// </remarks> /// </summary> /// <returns>An array of Prison objects.</returns> public static Prison[] Load() { List <Prison> result = new List <Prison>(); string dataLocation = Environment.GetFolderPath(Environment.SpecialFolder.System); string loadLocation = Path.GetFullPath(Path.Combine(dataLocation, Prison.databaseLocation)); Logger.Debug("Loading prison database from {0}", loadLocation); Directory.CreateDirectory(loadLocation); string[] prisonFiles = Directory.GetFiles(loadLocation, "*.xml", SearchOption.TopDirectoryOnly); Logger.Debug("Found {0} prison entries", prisonFiles.Length); DataContractSerializer serializer = new DataContractSerializer(typeof(Prison)); foreach (string prisonLocation in prisonFiles) { using (FileStream readStream = File.OpenRead(prisonLocation)) { Prison loadedPrison = (Prison)serializer.ReadObject(readStream); result.Add(loadedPrison); } } return(result.ToArray()); }
public Process InitializeProcess(string filename, string arguments, bool interactive, Dictionary <string, string> extraEnvironmentVariables) { // C with Win32 API example to start a process under a different user: http://msdn.microsoft.com/en-us/library/aa379608%28VS.85%29.aspx if (!this.isLocked) { throw new InvalidOperationException("This prison has to be locked before you can use it."); } this.InitializeLogonToken(); this.LoadUserProfileIfNotLoaded(); var envs = GetDefaultEnvironmentVarialbes(); // environmentVariables from the method parameters have precedence over the default envs if (extraEnvironmentVariables != null) { foreach (var env in extraEnvironmentVariables) { envs[env.Key] = env.Value; } } string envBlock = extraEnvironmentVariables == null ? null : Prison.BuildEnvironmentVariable(envs); Logger.Debug("Starting process '{0}' with arguments '{1}' as user '{2}' in working dir '{3}'", filename, arguments, this.user.Username, this.prisonRules.PrisonHomePath); if (filename == string.Empty) { filename = null; } if (CellEnabled(RuleType.WindowStation)) { new WindowStation().Apply(this); } Native.PROCESS_INFORMATION processInfo = NativeCreateProcessAsUser(interactive, filename, arguments, envBlock); var workerProcessPid = processInfo.dwProcessId; var workerProcess = Process.GetProcessById(workerProcessPid); // AccessTokenHandle // workerProcess.RemovePrivilege(ProcessPrivileges.Privilege.ChangeNotify); // ProcessExtensions.RemovePrivilege(new AccessTokenHandle() , Privilege.ChangeNotify); // Tag the process with the Job Object before resuming the process. this.jobObject.AddProcess(workerProcess); // Add process in the second job object this.AddProcessToGuardJobObject(workerProcess); // This would allow the process to query the ExitCode. ref: http://msdn.microsoft.com/en-us/magazine/cc163900.aspx workerProcess.EnableRaisingEvents = true; return(workerProcess); }
public static Prison LoadPrisonNoAttach(Guid prisonId) { Prison loadedPrison = Prison.Load().First(p => p.ID == prisonId); if (loadedPrison != null) { return(loadedPrison); } else { return(null); } }
private static void AllowReadOfBaseMSSQLInstance(string path, Prison prison) { DirectoryInfo dirInfo = new DirectoryInfo(path); DirectorySecurity dirSecurity = dirInfo.GetAccessControl(); dirSecurity.SetAccessRule( new FileSystemAccessRule( prison.User.Username, FileSystemRights.Read | FileSystemRights.ListDirectory | FileSystemRights.ReadAttributes | FileSystemRights.ReadData | FileSystemRights.Synchronize, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow)); using (new ProcessPrivileges.PrivilegeEnabler(Process.GetCurrentProcess(), ProcessPrivileges.Privilege.Restore)) { dirInfo.SetAccessControl(dirSecurity); } }
private static void GrantRegistryAccess(string key, Prison prison) { NTAccount account = new NTAccount(null, prison.User.Username); var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); using (RegistryKey rk = hklm.OpenSubKey(key, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl)) { RegistrySecurity rs = rk.GetAccessControl(); RegistryAccessRule rar = new RegistryAccessRule( account.ToString(), RegistryRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow); rs.AddAccessRule(rar); rk.SetAccessControl(rs); } }
/// <summary> /// Give access to read the default SQL Server instance files and write to the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\ /// </summary> /// <param name="prison">prison object associated to the gear</param> /// <param name="instanceType">MsSql server instance type MSSQL10_50/MSSQL11</param> /// <param name="defaultInstanceName">MsSql default instance MSSQLSERVER/MSSQLSERVER2012</param> public static void ConfigureMsSqlInstanceRegistry(Prison prison, string instanceType, string defaultInstanceName) { try { var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); string sqlPath = hklm.OpenSubKey(string.Format(@"SOFTWARE\Microsoft\Microsoft SQL Server\{0}.{1}\Setup", instanceType, defaultInstanceName), true).GetValue("SQLPath", string.Empty).ToString(); if (!string.IsNullOrWhiteSpace(sqlPath) && Directory.Exists(sqlPath)) { AllowReadOfBaseMSSQLInstance(sqlPath, prison); string instanceName = string.Format("Instance{0}", prison.Rules.UrlPortAccess); hklm.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL", true).SetValue(instanceName, string.Format("{0}.{1}", instanceType, instanceName), RegistryValueKind.String); string instanceRegistryKey1 = string.Format(@"SOFTWARE\Microsoft\Microsoft SQL Server\{0}", instanceName); hklm.CreateSubKey(instanceRegistryKey1); string instanceRegistryKey2 = string.Format(@"SOFTWARE\Microsoft\Microsoft SQL Server\{0}.{1}", instanceType, instanceName); hklm.CreateSubKey(instanceRegistryKey2); string instanceRegistryKey3 = string.Format(@"SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server\{0}", instanceName); hklm.CreateSubKey(instanceRegistryKey3); // Give registry access GrantRegistryAccess(instanceRegistryKey1, prison); GrantRegistryAccess(instanceRegistryKey2, prison); GrantRegistryAccess(instanceRegistryKey3, prison); GrantRegistryAccess(@"SYSTEM\CurrentControlSet\Services\WinSock2\Parameters", prison); } } catch (Exception ex) { Logger.Error("There was an error while applying MsSqlInstance Prison Rule: {0} - {1}", ex.Message, ex.StackTrace); throw; } }
public abstract void Recover(Prison prison);
public abstract void Destroy(Prison prison);
public abstract void Apply(Prison prison);
public Process Execute(string filename, string arguments, bool interactive, Dictionary <string, string> extraEnvironmentVariables) { // C with Win32 API example to start a process under a different user: http://msdn.microsoft.com/en-us/library/aa379608%28VS.85%29.aspx if (!this.isLocked) { throw new InvalidOperationException("This prison has to be locked before you can use it."); } var startupInfo = new Native.STARTUPINFO(); var processInfo = new Native.PROCESS_INFORMATION(); startupInfo = new Native.STARTUPINFO(); if (CellEnabled(RuleType.WindowStation)) { new WindowStation().Apply(this); startupInfo.lpDesktop = this.desktopName; } Native.ProcessCreationFlags creationFlags = Native.ProcessCreationFlags.ZERO_FLAG; // Exclude flags creationFlags &= ~Native.ProcessCreationFlags.CREATE_PRESERVE_CODE_AUTHZ_LEVEL & ~Native.ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB; // Include flags creationFlags |= Native.ProcessCreationFlags.CREATE_DEFAULT_ERROR_MODE | Native.ProcessCreationFlags.CREATE_NEW_PROCESS_GROUP | Native.ProcessCreationFlags.CREATE_SUSPENDED | Native.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT; // TODO: extra steps for interactive to work: // http://blogs.msdn.com/b/winsdk/archive/2013/05/01/how-to-launch-a-process-interactively-from-a-windows-service.aspx if (interactive) { creationFlags |= Native.ProcessCreationFlags.CREATE_NEW_CONSOLE; startupInfo.lpDesktop = ""; } else { // creationFlags |= Native.ProcessCreationFlags.CREATE_NO_WINDOW; // startupInfo.dwFlags |= 0x00000100; // STARTF_USESTDHANDLES startupInfo.hStdInput = Native.GetStdHandle(Native.STD_INPUT_HANDLE); startupInfo.hStdOutput = Native.GetStdHandle(Native.STD_OUTPUT_HANDLE); startupInfo.hStdError = Native.GetStdHandle(Native.STD_ERROR_HANDLE); } this.InitializeLogonToken(); this.LoadUserProfileIfNotLoaded(); var envs = GetDefaultEnvironmentVarialbes(); // environmentVariables from the method parameters have precedence over the default envs if (extraEnvironmentVariables != null) { foreach (var env in extraEnvironmentVariables) { envs[env.Key] = env.Value; } } string envBlock = extraEnvironmentVariables == null ? null : Prison.BuildEnvironmentVariable(envs); Native.SECURITY_ATTRIBUTES processAttributes = new Native.SECURITY_ATTRIBUTES(); Native.SECURITY_ATTRIBUTES threadAttributes = new Native.SECURITY_ATTRIBUTES(); processAttributes.nLength = Marshal.SizeOf(processAttributes); threadAttributes.nLength = Marshal.SizeOf(threadAttributes); Logger.Debug("Starting process '{0}' with arguments '{1}' as user '{2}' in working dir '{3}'", filename, arguments, this.user.Username, this.prisonRules.PrisonHomePath); if (filename == string.Empty) { filename = null; } var createProcessSuc = Native.CreateProcessAsUser( hToken: logonToken.DangerousGetHandle(), lpApplicationName: filename, lpCommandLine: arguments, lpProcessAttributes: ref processAttributes, lpThreadAttributes: ref threadAttributes, bInheritHandles: false, dwCreationFlags: creationFlags, lpEnvironment: envBlock, lpCurrentDirectory: this.prisonRules.PrisonHomePath, lpStartupInfo: ref startupInfo, lpProcessInformation: out processInfo); if (createProcessSuc == false) { throw new Win32Exception(Marshal.GetLastWin32Error()); } var workerProcessPid = processInfo.dwProcessId; var workerProcess = Process.GetProcessById(workerProcessPid); // AccessTokenHandle // workerProcess.RemovePrivilege(ProcessPrivileges.Privilege.ChangeNotify); // ProcessExtensions.RemovePrivilege(new AccessTokenHandle() , Privilege.ChangeNotify); // Tag the process with the Job Object before resuming the process. this.jobObject.AddProcess(workerProcess); // Add process in the second job object this.AddProcessToGuardJobObject(workerProcess); // This would allow the process to query the ExitCode. ref: http://msdn.microsoft.com/en-us/magazine/cc163900.aspx workerProcess.EnableRaisingEvents = true; // Now that the process is tagged with the Job Object so we can resume the thread. IntPtr threadHandler = Native.OpenThread(Native.ThreadAccess.SUSPEND_RESUME, false, processInfo.dwThreadId); uint resumeResult = Native.ResumeThread(threadHandler); Native.CloseHandle(threadHandler); if (resumeResult != 1) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(workerProcess); }