Skip to content

Commit 9d279be

Browse files
authored
Merge pull request #3723 from marticliment/Add-secure-settings-toggle
2 parents 9af1fbb + 6ce86ea commit 9d279be

23 files changed

Lines changed: 578 additions & 64 deletions

.deepsource.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ enabled = false # Disables standardjs transformer
6262

6363
[[transformers]]
6464
name = "prettier"
65-
enabled = false # Disables prettier transformer
65+
enabled = false # Disables prettier transformer

cli-arguments.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
| `--help` | Opens this page | 3.2.0+ |
1313
| `--import-settings file` | Imports UniGetUI settings from json file _file_. The file must exist. The old settings will be lost* | 3.2.0+ |
1414
| `--export-settings file` | Exports UniGetUI settings to json file _file_. The file will be created or overwritten* | 3.2.0+ |
15-
| `--enable-setting key` | Enables the boolean setting _key_* | 3.2.0+ |
16-
| `--disable-setting key` | Disables the boolean setting _key_* | 3.2.0+ |
15+
| `--[enable\|disable]-setting key` | Enables/disables the boolean setting _key_* | 3.2.0+ |
1716
| `--set-setting-value key value` | Sets the value _value_ to the non-boolean setting _key_. To clear a non-boolean setting, `--disable-setting` can be used* | 3.2.0+ |
1817
| `--no-corrupt-dialog` | Will show a verbose error message (the error report) instead of a simplified message dialog | 3.2.1+ |
18+
| `--[enable\|disable]-secure-setting-for-user username key` | Enables/disables the given secure setting for the given username. Requires administrator rights. | 3.2.1+ |
19+
| `--[enable\|disable]-secure-setting key` | Enables/disables the given secure setting for current user. This will generate a UAC prompt | 3.2.1+ |
1920

2021

2122
\*After modifying the settings, you must ensure that any running instance of UniGetUI is restarted for the changes to take effect
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using System.Diagnostics;
2+
using UniGetUI.Core.Data;
3+
using UniGetUI.Core.Tools;
4+
5+
namespace UniGetUI.Core.SettingsEngine.SecureSettings;
6+
7+
public static class SecureSettings
8+
{
9+
private static readonly Dictionary<string, bool> _cache = new();
10+
11+
public static class Args
12+
{
13+
public const string ENABLE_FOR_USER = "--enable-secure-setting-for-user";
14+
public const string DISABLE_FOR_USER = "--disable-secure-setting-for-user";
15+
}
16+
17+
public static bool Get(string setting)
18+
{
19+
string purifiedSetting = CoreTools.MakeValidFileName(setting);
20+
if (_cache.TryGetValue(purifiedSetting, out var value))
21+
{
22+
return value;
23+
}
24+
25+
string purifiedUser = CoreTools.MakeValidFileName(Environment.UserName);
26+
27+
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
28+
var settingsLocation = Path.Join(appData, "UniGetUI\\SecureSettings", purifiedUser);
29+
var settingFile = Path.Join(settingsLocation, purifiedSetting);
30+
31+
if (!Directory.Exists(settingsLocation))
32+
{
33+
_cache[purifiedSetting] = false;
34+
return false;
35+
}
36+
37+
bool exists = File.Exists(settingFile);
38+
_cache[purifiedSetting] = exists;
39+
return exists;
40+
}
41+
42+
public static async Task<bool> TrySet(string setting, bool enabled)
43+
{
44+
string purifiedSetting = CoreTools.MakeValidFileName(setting);
45+
_cache.Remove(purifiedSetting);
46+
47+
string purifiedUser = CoreTools.MakeValidFileName(Environment.UserName);
48+
49+
using Process p = new Process();
50+
p.StartInfo = new()
51+
{
52+
UseShellExecute = true,
53+
CreateNoWindow = true,
54+
FileName = CoreData.UniGetUIExecutableFile,
55+
Verb = "runas",
56+
ArgumentList =
57+
{
58+
enabled? Args.ENABLE_FOR_USER: Args.DISABLE_FOR_USER,
59+
purifiedUser,
60+
purifiedSetting
61+
}
62+
};
63+
64+
p.Start();
65+
await p.WaitForExitAsync();
66+
return p.ExitCode is 0;
67+
}
68+
69+
public static int ApplyForUser(string username, string setting, bool enable)
70+
{
71+
try
72+
{
73+
string purifiedSetting = CoreTools.MakeValidFileName(setting);
74+
_cache.Remove(purifiedSetting);
75+
76+
string purifiedUser = CoreTools.MakeValidFileName(username);
77+
78+
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
79+
var settingsLocation = Path.Join(appData, "UniGetUI\\SecureSettings", purifiedUser);
80+
var settingFile = Path.Join(settingsLocation, purifiedSetting);
81+
82+
if (!Directory.Exists(settingsLocation))
83+
{
84+
Directory.CreateDirectory(settingsLocation);
85+
}
86+
87+
if (enable)
88+
{
89+
File.WriteAllText(settingFile, "");
90+
}
91+
else
92+
{
93+
if (File.Exists(settingFile))
94+
{
95+
File.Delete(settingFile);
96+
}
97+
}
98+
99+
return 0;
100+
}
101+
catch (Exception ex)
102+
{
103+
Console.WriteLine(ex);
104+
return -1;
105+
}
106+
}
107+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<ItemGroup>
3+
<ProjectReference Include="..\UniGetUI.Core.Tools\UniGetUI.Core.Tools.csproj" />
4+
</ItemGroup>
5+
6+
<ItemGroup>
7+
<Compile Include="..\SharedAssemblyInfo.cs" Link="SharedAssemblyInfo.cs" />
8+
</ItemGroup>
9+
</Project>

src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
using System.Collections.Concurrent;
2-
using System.Runtime.InteropServices;
32
using System.Text.Json;
43
using System.Text.Json.Nodes;
5-
using ABI.Windows.UI.Text.Core;
64
using UniGetUI.Core.Data;
7-
using UniGetUI.Core.Language;
85
using UniGetUI.Core.Logging;
6+
using UniGetUI.Core.SettingsEngine.SecureSettings;
97
using UniGetUI.Core.Tools;
10-
using UniGetUI.PackageEngine.Enums;
118
using UniGetUI.PackageEngine.Interfaces;
129
using UniGetUI.PackageEngine.Serializable;
1310

@@ -90,7 +87,7 @@ public static InstallOptions LoadApplicable(
9087
if (no_integrity is not null) instance.SkipHashCheck = (bool)no_integrity;
9188
if (remove_data is not null) instance.RemoveDataOnUninstall = (bool)remove_data;
9289

93-
return instance;
90+
return EnsureSecureOptions(instance);
9491
}
9592

9693
/// <summary>
@@ -112,7 +109,7 @@ public static Task<InstallOptions> LoadApplicableAsync(
112109
bool? no_integrity = null,
113110
bool? remove_data = null,
114111
InstallOptions? overridePackageOptions = null)
115-
=> Task.Run(() => LoadApplicable(package, elevated, interactive, no_integrity, remove_data));
112+
=> Task.Run(() => LoadApplicable(package, elevated, interactive, no_integrity, remove_data, overridePackageOptions));
116113

117114
/*
118115
*
@@ -186,5 +183,33 @@ private static InstallOptions _loadFromDisk(string key)
186183
return new();
187184
}
188185
}
186+
187+
private static InstallOptions EnsureSecureOptions(InstallOptions options)
188+
{
189+
if (SecureSettings.Get("AllowCLIArguments"))
190+
{
191+
// If CLI arguments are allowed, sanitize them
192+
for (int i = 0; i < options.CustomParameters.Count; i++)
193+
{
194+
options.CustomParameters[i] = options.CustomParameters[i]
195+
.Replace("&", "")
196+
.Replace("|", "")
197+
.Replace(";", "")
198+
.Replace("<", "")
199+
.Replace(">", "")
200+
.Replace("\n", "");
201+
}
202+
}
203+
else
204+
{
205+
// Otherwhise, clear them
206+
if (options.CustomParameters.Count > 0)
207+
Logger.Warn($"Custom CLI parameters [{string.Join(' ', options.CustomParameters)}] will be discarded");
208+
209+
options.CustomParameters = [];
210+
}
211+
212+
return options;
213+
}
189214
}
190215
}

src/UniGetUI.PackageEngine.PackageManagerClasses/UniGetUI.PackageEngine.Classes.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<ProjectReference Include="..\UniGetUI.Core.Data\UniGetUI.Core.Data.csproj" />
88
<ProjectReference Include="..\UniGetUI.Core.IconStore\UniGetUI.Core.IconEngine.csproj" />
99
<ProjectReference Include="..\UniGetUI.Core.LanguageEngine\UniGetUI.Core.LanguageEngine.csproj" />
10+
<ProjectReference Include="..\UniGetUI.Core.SecureSettings\UniGetUI.Core.SecureSettings.csproj" />
1011
<ProjectReference Include="..\UniGetUI.Core.Settings\UniGetUI.Core.Settings.csproj" />
1112
<ProjectReference Include="..\UniGetUI.Core.Tools\UniGetUI.Core.Tools.csproj" />
1213
<ProjectReference Include="..\UniGetUI.PackageEngine.Enums\UniGetUI.PackageEngine.Structs.csproj" />

src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,6 @@ public override void LoadFromJson(JsonNode data)
6262
// This entry shall be checked the last one, to ensure all other properties are set
6363
this.OverridesNextLevelOpts =
6464
data[nameof(OverridesNextLevelOpts)]?.GetValue<bool>() ?? DiffersFromDefault();
65-
66-
SanitizeOptions();
67-
}
68-
69-
private void SanitizeOptions()
70-
{
71-
for (int i = 0; i < this.CustomParameters.Count; i++)
72-
{
73-
this.CustomParameters[i] = this.CustomParameters[i]
74-
.Replace("&", "")
75-
.Replace("|", "")
76-
.Replace(";", "")
77-
.Replace("<", "")
78-
.Replace(">", "")
79-
.Replace("\n", "");
80-
}
8165
}
8266

8367
public bool DiffersFromDefault()

src/UniGetUI.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{015B44EE
105105
EndProject
106106
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniGetUI.PackageEngine.Serializable.Tests", "UniGetUI.PackageEngine.Serializable.Tests\UniGetUI.PackageEngine.Serializable.Tests.csproj", "{F1610A61-5444-4C11-9447-13CCA327887E}"
107107
EndProject
108+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniGetUI.Core.SecureSettings", "UniGetUI.Core.SecureSettings\UniGetUI.Core.SecureSettings.csproj", "{B0E59327-933E-4DB0-BD2D-FB16EB9B4194}"
109+
EndProject
108110
Global
109111
GlobalSection(SolutionConfigurationPlatforms) = preSolution
110112
Debug|x64 = Debug|x64
@@ -271,6 +273,10 @@ Global
271273
{F1610A61-5444-4C11-9447-13CCA327887E}.Debug|x64.Build.0 = Debug|x64
272274
{F1610A61-5444-4C11-9447-13CCA327887E}.Release|x64.ActiveCfg = Release|x64
273275
{F1610A61-5444-4C11-9447-13CCA327887E}.Release|x64.Build.0 = Release|x64
276+
{B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Debug|x64.ActiveCfg = Debug|x64
277+
{B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Debug|x64.Build.0 = Debug|x64
278+
{B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Release|x64.ActiveCfg = Release|x64
279+
{B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Release|x64.Build.0 = Release|x64
274280
EndGlobalSection
275281
GlobalSection(SolutionProperties) = preSolution
276282
HideSolutionNode = FALSE
@@ -319,6 +325,7 @@ Global
319325
{3C8BF564-B4B5-44A7-9D8C-102C2F820EAF} = {8CF74C87-534F-4017-A4ED-F2918025E31A}
320326
{015B44EE-32AE-4105-9016-49140743CAF9} = {7940E867-EEBA-4AFD-9904-1536F003239C}
321327
{F1610A61-5444-4C11-9447-13CCA327887E} = {015B44EE-32AE-4105-9016-49140743CAF9}
328+
{B0E59327-933E-4DB0-BD2D-FB16EB9B4194} = {E05D1183-D360-4AFE-8968-314A34FAD3B2}
322329
EndGlobalSection
323330
GlobalSection(ExtensibilityGlobals) = postSolution
324331
SolutionGuid = {D044BB14-0B37-47E5-A579-8B30FCBA1F9F}

0 commit comments

Comments
 (0)