File: Verification\RpmVerifier.cs
Web Access
Project: src\src\SignCheck\Microsoft.SignCheck\Microsoft.DotNet.SignCheckLibrary.csproj (Microsoft.DotNet.SignCheckLibrary)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Build.Tasks.Installers;
using Microsoft.SignCheck.Logging;
 
namespace Microsoft.SignCheck.Verification
{
    public class RpmVerifier : LinuxPackageVerifier
    {
        public RpmVerifier(Log log, Exclusions exclusions, SignatureVerificationOptions options) : base(log, exclusions, options, ".rpm") { }
 
        protected override IEnumerable<ArchiveEntry> ReadArchiveEntries(string archivePath)
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                throw new PlatformNotSupportedException("RPM unpacking is only supported on Linux.");
            }
 
            using var stream = File.Open(archivePath, FileMode.Open);
            using RpmPackage rpmPackage = RpmPackage.Read(stream);
            using var dataStream = File.OpenWrite(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
            using var archive = new CpioReader(rpmPackage.ArchiveStream, leaveOpen: false);
 
            while (archive.GetNextEntry() is CpioEntry entry)
            {
                yield return new ArchiveEntry()
                {
                    RelativePath = entry.Name,
                    ContentStream = entry.DataStream,
                    ContentSize= entry.DataStream.Length
                };
            }
        }
 
        protected override (string signatureDocument, string signableContent) GetSignatureDocumentAndSignableContent(string archivePath, string tempDir)
        {
            string signatureDocument = Path.Combine(tempDir, "signableContent");
            string signableContent = Path.Combine(tempDir, "pgpSignableContent");
 
            using var rpmPackageStream = File.Open(archivePath, FileMode.Open);
            using (RpmPackage rpmPackage = RpmPackage.Read(rpmPackageStream))
            {
                var pgpEntry = rpmPackage.Signature.Entries.FirstOrDefault(e => e.Tag == RpmSignatureTag.PgpHeaderAndPayload).Value;
                if (pgpEntry == null)
                {
                    return (null, null);
                }
 
                File.WriteAllBytes(signatureDocument, [.. (ArraySegment<byte>)pgpEntry]);
            }
 
            using (var signableContentStream = File.Create(signableContent))
            {
                rpmPackageStream.Seek(0, SeekOrigin.Begin);
                RpmPackage.GetSignableContent(rpmPackageStream).CopyTo(signableContentStream);
            }
 
            return (signatureDocument, signableContent);
        }
    }
}