Skip to content

Commit 529c961

Browse files
authored
Merge pull request #1045 from corbob/996-check-config-dir
(#996) Create config directory if it doesn't exist
2 parents 86e6f63 + 600b9f8 commit 529c961

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs

+12-3
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,22 @@ protected override void Load(ContainerBuilder builder)
148148
var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true");
149149

150150
LiteDatabase globalDatabase;
151+
var globalConfigDirectory = Path.Combine(Bootstrapper.AppDataPath, "Config");
152+
var globalConfigDatabaseFile = Path.Combine(globalConfigDirectory, "data.db");
153+
151154
if (Hacks.IsElevated)
152155
{
153-
globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true");
156+
if (!Directory.Exists(globalConfigDirectory))
157+
{
158+
Directory.CreateDirectory(globalConfigDirectory);
159+
Hacks.LockDirectory(globalConfigDirectory);
160+
}
161+
162+
globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};upgrade=true");
154163
}
155164
else
156165
{
157-
if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")))
166+
if (!File.Exists(globalConfigDatabaseFile))
158167
{
159168
// Since the global configuration database file doesn't exist, we must be running in a state where an administrator user
160169
// has never run Chocolatey GUI. In this case, use null, which will mean attempts to use the global database will be ignored.
@@ -163,7 +172,7 @@ protected override void Load(ContainerBuilder builder)
163172
else
164173
{
165174
// Since this is a non-administrator user, they should only have read permissions to this database
166-
globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};readonly=true");
175+
globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};readonly=true");
167176
}
168177
}
169178

Source/ChocolateyGui.Common/Hacks.cs

+31
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,43 @@
55
// </copyright>
66
// --------------------------------------------------------------------------------------------------------------------
77

8+
using System;
9+
using System.IO;
10+
using System.Security.AccessControl;
811
using System.Security.Principal;
912

1013
namespace ChocolateyGui.Common
1114
{
1215
public static class Hacks
1316
{
1417
public static bool IsElevated => (WindowsIdentity.GetCurrent().Owner?.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid)).GetValueOrDefault(false);
18+
19+
// TODO: Replace this LockDirectory with calls to DotNetFileSystem's LockDirectory when https://github.com/chocolatey/ChocolateyGUI/issues/1046 is completed.
20+
/// <summary>
21+
/// Lock the given directory path to just Administrators being able to write. This method is copied from chocolatey.infrastructure.filesystem.DotNetFileSystem, and should be replaced with that call when the minimum Chocolatey.lib is bumped to 2.2.0 or greater.
22+
/// </summary>
23+
/// <param name="directoryPath">Directory path to lock down.</param>
24+
public static void LockDirectory(string directoryPath)
25+
{
26+
var permissions = Directory.GetAccessControl(directoryPath);
27+
var rules = permissions.GetAccessRules(includeExplicit: true, includeInherited: true, targetType: typeof(NTAccount));
28+
29+
// We first need to remove all rules
30+
foreach (FileSystemAccessRule rule in rules)
31+
{
32+
permissions.RemoveAccessRuleAll(rule);
33+
}
34+
35+
var bultinAdmins = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).Translate(typeof(NTAccount));
36+
var localsystem = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null).Translate(typeof(NTAccount));
37+
var builtinUsers = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null).Translate(typeof(NTAccount));
38+
var inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
39+
permissions.SetAccessRule(new FileSystemAccessRule(bultinAdmins, FileSystemRights.FullControl, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow));
40+
permissions.SetAccessRule(new FileSystemAccessRule(localsystem, FileSystemRights.FullControl, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow));
41+
permissions.SetAccessRule(new FileSystemAccessRule(builtinUsers, FileSystemRights.ReadAndExecute, inheritanceFlags, PropagationFlags.None, AccessControlType.Allow));
42+
permissions.SetOwner(bultinAdmins);
43+
permissions.SetAccessRuleProtection(isProtected: true, preserveInheritance: false);
44+
Directory.SetAccessControl(directoryPath, permissions);
45+
}
1546
}
1647
}

Source/ChocolateyGuiCli/Startup/ChocolateyGuiCliModule.cs

+12-3
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,22 @@ protected override void Load(ContainerBuilder builder)
4848
var userDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.LocalAppDataPath, "data.db")};upgrade=true");
4949

5050
LiteDatabase globalDatabase;
51+
var globalConfigDirectory = Path.Combine(Bootstrapper.AppDataPath, "Config");
52+
var globalConfigDatabaseFile = Path.Combine(globalConfigDirectory, "data.db");
53+
5154
if (Hacks.IsElevated)
5255
{
53-
globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};upgrade=true");
56+
if (!Directory.Exists(globalConfigDirectory))
57+
{
58+
Directory.CreateDirectory(globalConfigDirectory);
59+
Hacks.LockDirectory(globalConfigDirectory);
60+
}
61+
62+
globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};upgrade=true");
5463
}
5564
else
5665
{
57-
if (!File.Exists(Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")))
66+
if (!File.Exists(globalConfigDatabaseFile))
5867
{
5968
// Since the global configuration database file doesn't exist, we must be running in a state where an administrator user
6069
// has never run Chocolatey GUI. In this case, use null, which will mean attempts to use the global database will be ignored.
@@ -63,7 +72,7 @@ protected override void Load(ContainerBuilder builder)
6372
else
6473
{
6574
// Since this is a non-administrator user, they should only have read permissions to this database
66-
globalDatabase = new LiteDatabase($"filename={Path.Combine(Bootstrapper.AppDataPath, "Config", "data.db")};readonly=true");
75+
globalDatabase = new LiteDatabase($"filename={globalConfigDatabaseFile};readonly=true");
6776
}
6877
}
6978

0 commit comments

Comments
 (0)