| File: Signing\Verification\PackageSignatureVerifier.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.Packaging\NuGet.Packaging.csproj (NuGet.Packaging) |
// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using NuGet.Common; namespace NuGet.Packaging.Signing { public class PackageSignatureVerifier : IPackageSignatureVerifier { private readonly List<ISignatureVerificationProvider> _verificationProviders; public PackageSignatureVerifier(IEnumerable<ISignatureVerificationProvider> verificationProviders) { _verificationProviders = verificationProviders?.ToList() ?? throw new ArgumentNullException(nameof(verificationProviders)); } public async Task<VerifySignaturesResult> VerifySignaturesAsync(ISignedPackageReader package, SignedPackageVerifierSettings settings, CancellationToken token, Guid parentId = default(Guid)) { if (package == null) { throw new ArgumentNullException(nameof(package)); } if (settings == null) { throw new ArgumentNullException(nameof(settings)); } var valid = false; var trustResults = new List<PackageVerificationResult>(); var packageSigningTelemetryEvent = new PackageSigningTelemetryEvent(); using (var telemetry = TelemetryActivity.Create(parentId, packageSigningTelemetryEvent)) { var isSigned = await package.IsSignedAsync(token); if (isSigned) { try { var signature = await package.GetPrimarySignatureAsync(token); if (signature != null) { // Verify that the signature is trusted var sigTrustResults = await Task.WhenAll(_verificationProviders.Select(e => e.GetTrustResultAsync(package, signature, settings, token))); valid = IsValid(sigTrustResults); trustResults.AddRange(sigTrustResults); } else { valid = false; } } catch (SignatureException e) { // SignatureException generated while parsing signatures var issues = new[] { SignatureLog.Issue(!settings.AllowIllegal, e.Code, e.Message), SignatureLog.DebugLog(e.ToString()) }; trustResults.Add(new InvalidSignaturePackageVerificationResult( settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed, issues)); valid = settings.AllowIllegal; } catch (CryptographicException e) { // CryptographicException generated while parsing the SignedCms object var issues = new[] { SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3003, Strings.ErrorPackageSignatureInvalid), SignatureLog.DebugLog(e.ToString()) }; trustResults.Add(new InvalidSignaturePackageVerificationResult( settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed, issues)); valid = settings.AllowIllegal; } } else if (settings.AllowUnsigned) { // An unsigned package is valid only if unsigned packages are allowed. valid = true; } else { var issues = new[] { SignatureLog.Issue(fatal: true, code: NuGetLogCode.NU3004, message: Strings.ErrorPackageNotSigned) }; trustResults.Add(new UnsignedPackageVerificationResult( settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed, issues)); valid = false; } var status = valid ? NuGetOperationStatus.Succeeded : NuGetOperationStatus.Failed; packageSigningTelemetryEvent.SetResult(isSigned ? PackageSignType.Signed : PackageSignType.Unsigned, status); return new VerifySignaturesResult(valid, isSigned, trustResults); } } /// <summary> /// True if a provider trusts the package signature. /// </summary> private static bool IsValid(IEnumerable<PackageVerificationResult> verificationResults) { return verificationResults.Any() && verificationResults.All(e => e.Trust == SignatureVerificationStatus.Valid); } } }