-
Notifications
You must be signed in to change notification settings - Fork 384
Expand file tree
/
Copy pathDebVerifier.cs
More file actions
91 lines (78 loc) · 3.9 KB
/
DebVerifier.cs
File metadata and controls
91 lines (78 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Build.Tasks.Installers;
using Microsoft.SignCheck.Logging;
namespace Microsoft.SignCheck.Verification
{
public class DebVerifier : PgpVerifier
{
public DebVerifier(Log log, Exclusions exclusions, SignatureVerificationOptions options) : base(log, exclusions, options, ".deb") { }
protected override IEnumerable<ArchiveEntry> ReadArchiveEntries(string archivePath)
=> ReadDebContainerEntries(archivePath, "data.tar");
protected override (string signatureDocument, string signableContent) GetSignatureDocumentAndSignableContent(string archivePath, string tempDir)
{
string signatureDocument = null;
string signableContent = null;
try
{
string debianBinary = ExtractDebContainerEntry(archivePath, "debian-binary", tempDir);
string controlTar = ExtractDebContainerEntry(archivePath, "control.tar", tempDir);
string dataTar = ExtractDebContainerEntry(archivePath, "data.tar", tempDir);
signatureDocument = ExtractDebContainerEntry(archivePath, "_gpgorigin", tempDir);
signableContent = Path.Combine(tempDir, "signableContent");
Utils.RunBashCommand($"cat {debianBinary} {controlTar} {dataTar} > {signableContent}");
}
catch (FileNotFoundException)
{
// The signature document may be missing if the package is not signed.
}
return (signatureDocument, signableContent);
}
protected override void WriteArchiveEntry(ArchiveEntry archiveEntry, string targetPath)
=> File.WriteAllBytes(targetPath, ((MemoryStream)archiveEntry.ContentStream).ToArray());
/// <summary>
/// Read the entries in the deb container.
/// </summary>
private IEnumerable<ArchiveEntry> ReadDebContainerEntries(string archivePath, string match = null)
{
using var archive = new ArReader(File.OpenRead(archivePath), leaveOpen: false);
while (archive.GetNextEntry() is ArEntry entry)
{
string relativePath = entry.Name; // lgtm [cs/zipslip] Archive from trusted source
// The relative path ocassionally ends with a '/', which is not a valid path given that the path is a file.
// Remove the following workaround once https://github.com/dotnet/arcade/issues/15384 is resolved.
if (relativePath.EndsWith("/"))
{
relativePath = relativePath.TrimEnd('/');
}
if (match == null || relativePath.StartsWith(match))
{
yield return new ArchiveEntry()
{
RelativePath = relativePath,
ContentStream = entry.DataStream,
ContentSize = entry.DataStream.Length
};
}
}
}
/// <summary>
/// Extract a single entry from the deb container.
/// </summary>
private string ExtractDebContainerEntry(string archivePath, string entryName, string workingDir)
{
IEnumerable<ArchiveEntry> entries = ReadDebContainerEntries(archivePath, entryName);
if (!entries.Any())
{
throw new FileNotFoundException($"The entry '{entryName}' was not found in the archive '{archivePath}'");
}
ArchiveEntry archiveEntry = entries.First();
string entryPath = Path.Combine(workingDir, archiveEntry.RelativePath);
WriteArchiveEntry(archiveEntry, entryPath);
return entryPath;
}
}
}