Skip to content

Commit 6144c23

Browse files
authored
Merge pull request #36 from martincostello/target-dotnet-8
Target .NET 8
2 parents ccfaec5 + 05db3d9 commit 6144c23

18 files changed

+162
-151
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
*.lock.json
22
*.nuget.props
33
*.nuget.targets
4+
artifacts/
45
bin/
56
obj/
67
out/

AuthenticodeLint.sln

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 14
4-
VisualStudioVersion = 14.0.24720.0
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.7.34221.43
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuthenticodeLint", "AuthenticodeLint\AuthenticodeLint.csproj", "{FF77FAED-3274-4C0E-BDA0-98D8A5FA831E}"
77
EndProject

AuthenticodeLint/AuthenticodeLint.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<OutputType>WinExe</OutputType>
44
<AssemblyName>authlint</AssemblyName>
55
<PackageId>AuthenticodeLint</PackageId>
6-
<TargetFramework>net6.0</TargetFramework>
7-
<VersionPrefix>0.12.0</VersionPrefix>
6+
<TargetFramework>net8.0</TargetFramework>
7+
<VersionPrefix>0.13.0</VersionPrefix>
88
<Authors>Kevin Jones</Authors>
99
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
10-
<Copyright>Kevin Jones 2016-2021</Copyright>
10+
<Copyright>Kevin Jones 2016-2025</Copyright>
1111
<PackAsTool>true</PackAsTool>
1212
<ToolCommandName>authlint</ToolCommandName>
1313
<Description>Authenticode Lint is a Windows command-line tool for linting an examining an Authenticode signed file.</Description>
@@ -20,6 +20,6 @@
2020
<Nullable>enable</Nullable>
2121
</PropertyGroup>
2222
<ItemGroup>
23-
<PackageReference Include="AuthenticodeExaminer" Version="0.3.0" />
23+
<PackageReference Include="AuthenticodeExaminer" Version="0.4.0" />
2424
</ItemGroup>
2525
</Project>

AuthenticodeLint/Extraction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class Extraction
1111
{
1212
public static void ExtractToDisk(string file, CheckConfiguration configuration, IReadOnlyList<ICmsSignature> signatureGraph)
1313
{
14-
var fileDirectory = Path.Combine(configuration.ExtractPath, Path.GetFileName(file));
14+
var fileDirectory = Path.Combine(configuration.ExtractPath!, Path.GetFileName(file));
1515
if (Directory.Exists(fileDirectory))
1616
{
1717
Directory.Delete(fileDirectory, true);

AuthenticodeLint/Program.cs

Lines changed: 135 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -11,174 +11,182 @@ class Program
1111
{
1212
static int Main(string[] args)
1313
{
14-
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
15-
{
16-
Console.Error.WriteLine("AuthenticodeLint is only supported on Windows.");
17-
return ExitCodes.PlatformNotSupported;
18-
}
19-
var cli = Environment.CommandLine;
20-
List<CommandLineParameter>? parsedCommandLine;
2114
try
2215
{
23-
var commandLine = CommandLineParser.LexCommandLine(cli).Skip(1);
24-
parsedCommandLine = CommandLineParser.CreateCommandLineParametersWithValues(commandLine).ToList();
25-
}
26-
catch(InvalidOperationException)
27-
{
28-
parsedCommandLine = null;
29-
}
16+
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
17+
{
18+
Console.Error.WriteLine("AuthenticodeLint is only supported on Windows.");
19+
return ExitCodes.PlatformNotSupported;
20+
}
21+
var cli = Environment.CommandLine;
22+
List<CommandLineParameter>? parsedCommandLine;
23+
try
24+
{
25+
var commandLine = CommandLineParser.LexCommandLine(cli).Skip(1);
26+
parsedCommandLine = CommandLineParser.CreateCommandLineParametersWithValues(commandLine).ToList();
27+
}
28+
catch (InvalidOperationException)
29+
{
30+
parsedCommandLine = null;
31+
}
3032

31-
if (parsedCommandLine == null || parsedCommandLine.Count == 0 || parsedCommandLine.Any(cl => cl.Name == "help"))
32-
{
33-
ShowHelp();
34-
//Avoid returning success for printing help so that automated build systems do not interpret "show the help"
35-
//As a successful build incase the build system is incorrectly passing arguments.
36-
return ExitCodes.InvalidInputOrConfig;
37-
}
38-
var inputs = new List<string>();
39-
var suppress = new HashSet<int>();
40-
bool quiet = false;
41-
bool verbose = false;
42-
string? report = null;
43-
string? extract = null;
44-
var revocation = RevocationChecking.None;
45-
var ruleSet = RuleSet.Modern;
46-
foreach(var parameter in parsedCommandLine)
47-
{
48-
if (parameter.Name == "in")
33+
if (parsedCommandLine == null || parsedCommandLine.Count == 0 || parsedCommandLine.Any(cl => cl.Name == "help"))
34+
{
35+
ShowHelp();
36+
//Avoid returning success for printing help so that automated build systems do not interpret "show the help"
37+
//As a successful build incase the build system is incorrectly passing arguments.
38+
return ExitCodes.InvalidInputOrConfig;
39+
}
40+
var inputs = new List<string>();
41+
var suppress = new HashSet<int>();
42+
bool quiet = false;
43+
bool verbose = false;
44+
string? report = null;
45+
string? extract = null;
46+
var revocation = RevocationChecking.None;
47+
var ruleSet = RuleSet.Modern;
48+
foreach (var parameter in parsedCommandLine)
4949
{
50-
if (string.IsNullOrWhiteSpace(parameter.Value))
50+
if (parameter.Name == "in")
5151
{
52-
Console.Error.WriteLine("A value is required for input.");
53-
return ExitCodes.InvalidInputOrConfig;
52+
if (string.IsNullOrWhiteSpace(parameter.Value))
53+
{
54+
Console.Error.WriteLine("A value is required for input.");
55+
return ExitCodes.InvalidInputOrConfig;
56+
}
57+
var filePattern = Path.GetFileName(parameter.Value);
58+
//The value contains a pattern.
59+
if (filePattern.Contains('*') || filePattern.Contains('?'))
60+
{
61+
var directory = Path.GetDirectoryName(parameter.Value);
62+
if (Directory.Exists(directory))
63+
{
64+
var files = Directory.GetFiles(directory, filePattern, SearchOption.TopDirectoryOnly);
65+
inputs.AddRange(files);
66+
}
67+
}
68+
else
69+
{
70+
inputs.Add(parameter.Value);
71+
}
5472
}
55-
var filePattern = Path.GetFileName(parameter.Value);
56-
//The value contains a pattern.
57-
if (filePattern.Contains('*') || filePattern.Contains('?'))
73+
else if (parameter.Name == "suppress")
5874
{
59-
var directory = Path.GetDirectoryName(parameter.Value);
60-
if (Directory.Exists(directory))
75+
if (string.IsNullOrWhiteSpace(parameter.Value))
6176
{
62-
var files = Directory.GetFiles(directory, filePattern, SearchOption.TopDirectoryOnly);
63-
inputs.AddRange(files);
77+
ShowInvalidSuppression();
78+
return ExitCodes.InvalidInputOrConfig;
79+
}
80+
foreach (var idString in parameter.Value.Split(',').Select(p => p.Trim()))
81+
{
82+
int id;
83+
if (int.TryParse(idString, out id))
84+
{
85+
suppress.Add(id);
86+
}
87+
else
88+
{
89+
Console.Error.WriteLine($"{idString} is not a valid error ID.");
90+
return ExitCodes.InvalidInputOrConfig;
91+
}
6492
}
6593
}
66-
else
94+
else if (parameter.Name == "q" || parameter.Name == "quiet")
6795
{
68-
inputs.Add(parameter.Value);
96+
if (!string.IsNullOrWhiteSpace(parameter.Value))
97+
{
98+
Console.Error.WriteLine($"-{parameter.Name} does not expect a value.");
99+
return ExitCodes.InvalidInputOrConfig;
100+
}
101+
quiet = true;
69102
}
70-
}
71-
else if (parameter.Name == "suppress")
72-
{
73-
if (string.IsNullOrWhiteSpace(parameter.Value))
103+
else if (parameter.Name == "verbose")
74104
{
75-
ShowInvalidSuppression();
76-
return ExitCodes.InvalidInputOrConfig;
105+
if (!string.IsNullOrWhiteSpace(parameter.Value))
106+
{
107+
Console.Error.WriteLine($"-{parameter.Name} does not expect a value.");
108+
return ExitCodes.InvalidInputOrConfig;
109+
}
110+
verbose = true;
111+
}
112+
113+
else if (parameter.Name == "report")
114+
{
115+
report = parameter.Value;
116+
}
117+
else if (parameter.Name == "extract")
118+
{
119+
extract = parameter.Value;
77120
}
78-
foreach(var idString in parameter.Value.Split(',').Select(p => p.Trim()))
121+
else if (parameter.Name == "revocation")
79122
{
80-
int id;
81-
if (int.TryParse(idString, out id))
123+
if (string.IsNullOrWhiteSpace(parameter.Value))
82124
{
83-
suppress.Add(id);
125+
Console.Error.WriteLine($"-{parameter.Name} requires a value if specified.");
126+
return ExitCodes.InvalidInputOrConfig;
84127
}
85-
else
128+
if (!Enum.TryParse(parameter.Value, true, out revocation))
86129
{
87-
Console.Error.WriteLine($"{idString} is not a valid error ID.");
130+
Console.Error.WriteLine($"-{parameter.Value} is an unrecognized revocation mode.");
88131
return ExitCodes.InvalidInputOrConfig;
89132
}
90133
}
91-
}
92-
else if (parameter.Name == "q" || parameter.Name == "quiet")
93-
{
94-
if (!string.IsNullOrWhiteSpace(parameter.Value))
134+
else if (parameter.Name == "ruleset")
95135
{
96-
Console.Error.WriteLine($"-{parameter.Name} does not expect a value.");
97-
return ExitCodes.InvalidInputOrConfig;
136+
if (string.IsNullOrWhiteSpace(parameter.Value))
137+
{
138+
Console.Error.WriteLine($"-{parameter.Name} requires a value if specified.");
139+
return ExitCodes.InvalidInputOrConfig;
140+
}
141+
if (!Enum.TryParse(parameter.Value, true, out ruleSet) || parameter.Value.Equals("all", StringComparison.OrdinalIgnoreCase))
142+
{
143+
Console.Error.WriteLine($"-{parameter.Value} is an unrecognized ruleset.");
144+
return ExitCodes.InvalidInputOrConfig;
145+
}
98146
}
99-
quiet = true;
100-
}
101-
else if (parameter.Name == "verbose")
102-
{
103-
if (!string.IsNullOrWhiteSpace(parameter.Value))
147+
else
104148
{
105-
Console.Error.WriteLine($"-{parameter.Name} does not expect a value.");
149+
Console.Error.WriteLine($"-{parameter.Name} is an unknown parameter.");
106150
return ExitCodes.InvalidInputOrConfig;
107151
}
108-
verbose = true;
109152
}
153+
if (inputs.Count == 0)
154+
{
155+
Console.Error.WriteLine("Input is expected. See -help for usage.");
156+
return ExitCodes.InvalidInputOrConfig;
157+
}
158+
var configuration = new CheckConfiguration(inputs, report, quiet, suppress, verbose, revocation, extract, ruleSet);
110159

111-
else if (parameter.Name == "report")
160+
if (!ConfigurationValidator.ValidateAndPrint(configuration, Console.Error))
112161
{
113-
report = parameter.Value;
162+
return ExitCodes.InvalidInputOrConfig;
114163
}
115-
else if (parameter.Name == "extract")
164+
var collectors = new List<IRuleResultCollector>();
165+
if (!quiet)
116166
{
117-
extract = parameter.Value;
167+
collectors.Add(new StdOutRuleResultCollector());
118168
}
119-
else if (parameter.Name == "revocation")
169+
if (!string.IsNullOrWhiteSpace(report))
120170
{
121-
if (string.IsNullOrWhiteSpace(parameter.Value))
122-
{
123-
Console.Error.WriteLine($"-{parameter.Name} requires a value if specified.");
124-
return ExitCodes.InvalidInputOrConfig;
125-
}
126-
if (!Enum.TryParse(parameter.Value, true, out revocation))
127-
{
128-
Console.Error.WriteLine($"-{parameter.Value} is an unrecognized revocation mode.");
129-
return ExitCodes.InvalidInputOrConfig;
130-
}
171+
collectors.Add(new XmlRuleResultCollector(report));
131172
}
132-
else if (parameter.Name == "ruleset")
173+
var result = ExitCodes.Success;
174+
foreach (var file in inputs)
133175
{
134-
if (string.IsNullOrWhiteSpace(parameter.Value))
176+
var signatures = SignatureTreeInspector.Extract(file);
177+
if (CheckEngine.Instance.RunAllRules(file, signatures, collectors, configuration) != RuleEngineResult.AllPass)
135178
{
136-
Console.Error.WriteLine($"-{parameter.Name} requires a value if specified.");
137-
return ExitCodes.InvalidInputOrConfig;
138-
}
139-
if (!Enum.TryParse(parameter.Value, true, out ruleSet) || parameter.Value.Equals("all", StringComparison.OrdinalIgnoreCase))
140-
{
141-
Console.Error.WriteLine($"-{parameter.Value} is an unrecognized ruleset.");
142-
return ExitCodes.InvalidInputOrConfig;
179+
result = ExitCodes.ChecksFailed;
143180
}
144181
}
145-
else
146-
{
147-
Console.Error.WriteLine($"-{parameter.Name} is an unknown parameter.");
148-
return ExitCodes.InvalidInputOrConfig;
149-
}
182+
collectors.ForEach(c => c.Flush());
183+
return result;
150184
}
151-
if (inputs.Count == 0)
185+
catch (Exception ex)
152186
{
153-
Console.Error.WriteLine("Input is expected. See -help for usage.");
154-
return ExitCodes.InvalidInputOrConfig;
155-
}
156-
var configuration = new CheckConfiguration(inputs, report, quiet, suppress, verbose, revocation, extract, ruleSet);
157-
158-
if (!ConfigurationValidator.ValidateAndPrint(configuration, Console.Error))
159-
{
160-
return ExitCodes.InvalidInputOrConfig;
161-
}
162-
var collectors = new List<IRuleResultCollector>();
163-
if (!quiet)
164-
{
165-
collectors.Add(new StdOutRuleResultCollector());
166-
}
167-
if (!string.IsNullOrWhiteSpace(report))
168-
{
169-
collectors.Add(new XmlRuleResultCollector(report));
170-
}
171-
var result = ExitCodes.Success;
172-
foreach (var file in inputs)
173-
{
174-
var signatures = SignatureTreeInspector.Extract(file);
175-
if (CheckEngine.Instance.RunAllRules(file, signatures, collectors, configuration) != RuleEngineResult.AllPass)
176-
{
177-
result = ExitCodes.ChecksFailed;
178-
}
187+
Console.Error.WriteLine(ex.ToString());
188+
return ExitCodes.UnknownResults;
179189
}
180-
collectors.ForEach(c => c.Flush());
181-
return result;
182190
}
183191

184192
static void ShowInvalidSuppression() => Console.Error.WriteLine("Invalid list of errors to suppress. Use -help for more information.");

AuthenticodeLint/Rules/10000-Sha1PrimarySignatureRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public RuleResult Validate(IReadOnlyList<ICmsSignature> graph, SignatureLogger v
2020
return RuleResult.Fail;
2121
}
2222
var primary = graph[0];
23-
if (primary.DigestAlgorithm.Value != KnownOids.SHA1)
23+
if (primary.DigestAlgorithm!.Value != KnownOids.SHA1)
2424
{
2525
verboseWriter.LogSignatureMessage(primary, $"Expected {nameof(KnownOids.SHA1)} digest algorithm but is {primary.DigestAlgorithm.FriendlyName}.");
2626
return RuleResult.Fail;

AuthenticodeLint/Rules/10001-Sha2SignatureExistsRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public RuleResult Validate(IReadOnlyList<ICmsSignature> graph, SignatureLogger v
1818
{
1919
var signatures = graph.VisitAll(SignatureKind.AnySignature);
2020
if (signatures.Any(s =>
21-
s.DigestAlgorithm.Value == KnownOids.SHA256 ||
21+
s.DigestAlgorithm!.Value == KnownOids.SHA256 ||
2222
s.DigestAlgorithm.Value == KnownOids.SHA384 ||
2323
s.DigestAlgorithm.Value == KnownOids.SHA512))
2424
{

AuthenticodeLint/Rules/10002-NoWeakFileDigestAlgorithmsRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public RuleResult Validate(IReadOnlyList<ICmsSignature> graph, SignatureLogger v
1919
var result = RuleResult.Pass;
2020
foreach(var signature in signatures)
2121
{
22-
if (signature.DigestAlgorithm.Value == KnownOids.MD2)
22+
if (signature.DigestAlgorithm!.Value == KnownOids.MD2)
2323
{
2424
verboseWriter.LogSignatureMessage(signature, $"Uses the {nameof(KnownOids.MD2)} digest algorithm.");
2525
result = RuleResult.Fail;

0 commit comments

Comments
 (0)