Exemplo n.º 1
0
        /// <summary>
        /// Get timestamps from the signer info
        /// </summary>
        /// <param name="signer"></param>
        /// <returns></returns>
        private static IReadOnlyList <Timestamp> GetTimestamps(SignerInfo signer, string signatureFriendlyName)
        {
            var unsignedAttributes = signer.UnsignedAttributes;

            var timestampList = new List <Timestamp>();

            foreach (var attribute in unsignedAttributes)
            {
                if (string.Equals(attribute.Oid.Value, Oids.SignatureTimeStampTokenAttribute, StringComparison.Ordinal))
                {
                    var timestampCms = new SignedCms();
                    timestampCms.Decode(attribute.Values[0].RawData);

                    using (var certificates = SignatureUtility.GetTimestampCertificates(
                               timestampCms,
                               SigningSpecifications.V1,
                               signatureFriendlyName))
                    {
                        if (certificates == null || certificates.Count == 0)
                        {
                            throw new SignatureException(NuGetLogCode.NU3029, Strings.InvalidTimestampSignature);
                        }
                    }

                    timestampList.Add(new Timestamp(timestampCms));
                }
            }

            return(timestampList);
        }
Exemplo n.º 2
0
        private PackageVerificationResult VerifySignatureAndCountersignature(
            PrimarySignature signature,
            SignedPackageVerifierSettings settings)
        {
            var issues = new List <SignatureLog>();
            var certificateExtraStore = signature.SignedCms.Certificates;
            var primarySignatureHasCountersignature = SignatureUtility.HasRepositoryCountersignature(signature);
            var status = SignatureVerificationStatus.Illegal;

            // Only accept untrusted root if the signature has a countersignature that we can validate against
            var verifySettings = new SignatureVerifySettings(
                treatIssuesAsErrors: !settings.AllowIllegal,
                allowUntrustedRoot: primarySignatureHasCountersignature,
                allowUnknownRevocation: settings.AllowUnknownRevocation,
                logOnSignatureExpired: !primarySignatureHasCountersignature);

            var primarySummary = VerifyValidityAndTrust(signature, settings, verifySettings, certificateExtraStore, issues);

            if (primarySummary != null)
            {
                status = primarySummary.Status;

                if (primarySignatureHasCountersignature)
                {
                    if (settings.AlwaysVerifyCountersignature || ShouldFallbackToRepositoryCountersignature(primarySummary))
                    {
                        var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(signature);
                        verifySettings = new SignatureVerifySettings(
                            treatIssuesAsErrors: !settings.AllowIllegal,
                            allowUntrustedRoot: false,
                            allowUnknownRevocation: settings.AllowUnknownRevocation,
                            logOnSignatureExpired: true);

                        var counterSummary = VerifyValidityAndTrust(countersignature, settings, verifySettings, certificateExtraStore, issues);
                        status = counterSummary.Status;

                        if (!Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, counterSummary.Timestamp))
                        {
                            issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3011, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureNotTimeValid, signature.FriendlyName)));
                            status = SignatureVerificationStatus.Illegal;
                        }
                    }
                    else if (primarySummary.Flags.HasFlag(SignatureVerificationStatusFlags.CertificateExpired))
                    {
                        // We are not adding this log if the primary signature has a countersignature to check the expiration against the countersignature's timestamp.
                        // If the countersignature shouldn't be check and the primary signature was expired, add this log.
                        issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3011, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureNotTimeValid, signature.FriendlyName)));
                    }
                }
            }

            return(new SignedPackageVerificationResult(status, signature, issues));
        }
Exemplo n.º 3
0
        private static void VerifySigningCertificate(
            SignedCms signedCms,
            SignerInfo signerInfo,
            SigningSpecifications signingSpecifications)
        {
            var certificates = SignatureUtility.GetPrimarySignatureCertificates(
                signedCms,
                signerInfo,
                signingSpecifications);

            if (certificates == null || certificates.Count == 0)
            {
                ThrowForInvalidPrimarySignature();
            }
        }
Exemplo n.º 4
0
 private static void VerifySigningCertificate(
     SignedCms signedCms,
     SignerInfo signerInfo,
     SigningSpecifications signingSpecifications)
 {
     using (var certificates = SignatureUtility.GetCertificateChain(
                signedCms,
                signerInfo,
                signingSpecifications,
                Strings.PrimarySignatureFriendlyName))
     {
         if (certificates == null || certificates.Count == 0)
         {
             ThrowForInvalidPrimarySignature();
         }
     }
 }
        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));
        }
Exemplo n.º 6
0
        /// <summary>
        /// Add a signature to a package.
        /// </summary>
        public static async Task SignAsync(SigningOptions options, SignPackageRequest signRequest, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();

            Verify(signRequest, options.Logger);

            var    tempPackageFile       = new FileInfo(Path.GetTempFileName());
            Stream unsignedPackageStream = null;
            var    signaturePlacement    = SignaturePlacement.PrimarySignature;

            try
            {
                PrimarySignature primarySignature;
                var isSigned = false;

                using (var package = new SignedPackageArchive(options.InputPackageStream, Stream.Null))
                {
                    if (await package.IsZip64Async(token))
                    {
                        throw new SignatureException(NuGetLogCode.NU3006, Strings.ErrorZip64NotSupported);
                    }

                    primarySignature = await package.GetPrimarySignatureAsync(token);

                    isSigned = primarySignature != null;

                    if (signRequest.SignatureType == SignatureType.Repository && primarySignature != null)
                    {
                        if (primarySignature.Type == SignatureType.Repository)
                        {
                            throw new SignatureException(NuGetLogCode.NU3033, Strings.Error_RepositorySignatureMustNotHaveARepositoryCountersignature);
                        }

                        if (SignatureUtility.HasRepositoryCountersignature(primarySignature))
                        {
                            throw new SignatureException(NuGetLogCode.NU3032, Strings.SignedPackagePackageAlreadyCountersigned);
                        }

                        signaturePlacement = SignaturePlacement.Countersignature;
                    }

                    if (isSigned && !options.Overwrite && signaturePlacement != SignaturePlacement.Countersignature)
                    {
                        throw new SignatureException(NuGetLogCode.NU3001, Strings.SignedPackageAlreadySigned);
                    }
                }

                var inputPackageStream = options.InputPackageStream;
                if (isSigned)
                {
                    unsignedPackageStream = tempPackageFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite);

                    using (var package = new SignedPackageArchive(options.InputPackageStream, unsignedPackageStream))
                    {
                        await package.RemoveSignatureAsync(token);
                    }

                    inputPackageStream = unsignedPackageStream;
                }

                using (var package = new SignedPackageArchive(inputPackageStream, options.OutputPackageStream))
                {
                    PrimarySignature signature;
                    if (signaturePlacement == SignaturePlacement.Countersignature)
                    {
                        signature = await options.SignatureProvider.CreateRepositoryCountersignatureAsync(
                            signRequest as RepositorySignPackageRequest,
                            primarySignature,
                            options.Logger,
                            token);
                    }
                    else
                    {
                        var hashAlgorithm  = signRequest.SignatureHashAlgorithm;
                        var zipArchiveHash = await package.GetArchiveHashAsync(hashAlgorithm, token);

                        var signatureContent = GenerateSignatureContent(hashAlgorithm, zipArchiveHash);
                        signature = await options.SignatureProvider.CreatePrimarySignatureAsync(signRequest, signatureContent, options.Logger, token);
                    }

                    using (var stream = new MemoryStream(signature.GetBytes()))
                    {
                        await package.AddSignatureAsync(stream, token);
                    }
                }
            }
            finally
            {
                if (unsignedPackageStream != null && !ReferenceEquals(unsignedPackageStream, options.InputPackageStream))
                {
                    unsignedPackageStream.Dispose();
                }

                FileUtility.Delete(tempPackageFile.FullName);
            }
        }