private bool ShouldFallbackToRepositoryCountersignature(SignatureVerificationSummary primarySummary) { return(primarySummary.SignatureType == SignatureType.Author && ((primarySummary.Status == SignatureVerificationStatus.Illegal && primarySummary.Flags == SignatureVerificationStatusFlags.CertificateExpired) || (primarySummary.Status == SignatureVerificationStatus.Valid && primarySummary.Flags.HasFlag(SignatureVerificationStatusFlags.UntrustedRoot)))); }
private PackageVerificationResult Verify( PrimarySignature signature, SignedPackageVerifierSettings settings) { var certificateExtraStore = signature.SignedCms.Certificates; var repositoryCountersignatureExists = SignatureUtility.HasRepositoryCountersignature(signature); var isRepositoryCountersignatureVerificationRequested = settings.VerificationTarget.HasFlag(VerificationTarget.Repository) && settings.SignaturePlacement.HasFlag(SignaturePlacement.Countersignature); var allowDeferralToRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists; var status = SignatureVerificationStatus.Unknown; var issues = Enumerable.Empty <SignatureLog>(); var isUntrustedRootAllowed = IsUntrustedRootAllowed(signature); var verifySettings = new SignatureVerifySettings( allowIllegal: settings.AllowIllegal, allowUntrusted: settings.AllowUntrusted || isUntrustedRootAllowed, allowUnknownRevocation: settings.AllowUnknownRevocation, reportUnknownRevocation: settings.ReportUnknownRevocation, reportUntrustedRoot: !isUntrustedRootAllowed, revocationMode: settings.RevocationMode); SignatureVerificationSummary primarySummary = null; if (settings.SignaturePlacement.HasFlag(SignaturePlacement.PrimarySignature) && VerificationUtility.IsVerificationTarget(signature.Type, settings.VerificationTarget)) { primarySummary = VerifyValidityAndTrust(signature, settings, verifySettings, certificateExtraStore); issues = issues.Concat(primarySummary.Issues); status = primarySummary.Status; } Debug.Assert(isRepositoryCountersignatureVerificationRequested != (settings.RepositoryCountersignatureVerificationBehavior == SignatureVerificationBehavior.Never)); bool shouldVerifyRepositoryCountersignature; switch (settings.RepositoryCountersignatureVerificationBehavior) { case SignatureVerificationBehavior.IfExists: shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists; break; case SignatureVerificationBehavior.IfExistsAndIsNecessary: // The repository countersignature should be evaluated if settings allow it, if a repository countersignature exists // and if either settings only allow a repository countersignature to be evaluated or the primary signature has some // validation/trust issues that may benefit from a repository countersignature fallback. shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists && (primarySummary == null || (primarySummary != null && (HasUntrustedRoot(primarySummary) || IsSignatureExpired(primarySummary)))); break; case SignatureVerificationBehavior.Always: shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested; break; case SignatureVerificationBehavior.Never: shouldVerifyRepositoryCountersignature = false; break; default: throw new NotImplementedException(); } if (shouldVerifyRepositoryCountersignature) { var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(signature); if (countersignature == null) { if (settings.RepositoryCountersignatureVerificationBehavior == SignatureVerificationBehavior.Always) { issues = issues.Concat(new[] { SignatureLog.Error(NuGetLogCode.NU3038, Strings.NoRepositoryCountersignature) }); status = SignatureVerificationStatus.Disallowed; } } else { isUntrustedRootAllowed = IsUntrustedRootAllowed(countersignature); verifySettings = new SignatureVerifySettings( allowIllegal: settings.AllowIllegal, allowUntrusted: settings.AllowUntrusted || isUntrustedRootAllowed, allowUnknownRevocation: settings.AllowUnknownRevocation, reportUnknownRevocation: settings.ReportUnknownRevocation, reportUntrustedRoot: !isUntrustedRootAllowed, revocationMode: settings.RevocationMode); var countersignatureSummary = VerifyValidityAndTrust(countersignature, settings, verifySettings, certificateExtraStore); if (primarySummary == null) { status = countersignatureSummary.Status; } else { if (countersignatureSummary.Status == SignatureVerificationStatus.Valid) { if (IsSignatureExpired(primarySummary) && HasUntrustedRoot(primarySummary)) { // Exclude the issue of the primary signature being untrusted since the repository countersignature fulfills the role of a trust anchor. issues = issues.Where(log => log.Code != NuGetLogCode.NU3018); if (countersignatureSummary.Timestamp != null && Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, countersignatureSummary.Timestamp)) { // Exclude the issue of the primary signature being expired since the repository countersignature fulfills the role of a trusted timestamp. issues = issues.Where(log => log.Code != NuGetLogCode.NU3037); status = SignatureVerificationStatus.Valid; } } else if (IsSignatureExpired(primarySummary) && countersignatureSummary.Timestamp != null && Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, countersignatureSummary.Timestamp)) { // Exclude the issue of the primary signature being expired since the repository countersignature fulfills the role of a trusted timestamp. issues = issues.Where(log => log.Code != NuGetLogCode.NU3037); status = SignatureVerificationStatus.Valid; } else if (HasUntrustedRoot(primarySummary)) { // Exclude the issue of the primary signature being untrusted since the repository countersignature fulfills the role of a trust anchor. issues = issues.Where(log => log.Code != NuGetLogCode.NU3018); status = SignatureVerificationStatus.Valid; } } // Both the primary signature and the repository countersignature were evaluated. // The overall status should be the more severe status of the two. status = (SignatureVerificationStatus)Math.Min((int)status, (int)countersignatureSummary.Status); } issues = issues.Concat(countersignatureSummary.Issues); } } return(new SignedPackageVerificationResult(status, signature, issues)); }
private static bool IsSignatureExpired(SignatureVerificationSummary summary) { return(summary.SignatureType != SignatureType.Repository && summary.ExpirationTime.HasValue); }
private static bool HasUntrustedRoot(SignatureVerificationSummary summary) { return(summary.SignatureType != SignatureType.Repository && summary.Status != SignatureVerificationStatus.Valid && summary.Flags.HasFlag(SignatureVerificationStatusFlags.UntrustedRoot)); }