File: Signing\TrustStore\FallbackCertificateBundleX509ChainFactory.cs
Web Access
Project: src\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.

#if NET5_0_OR_GREATER

using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Threading;

namespace NuGet.Packaging.Signing
{
    internal sealed class FallbackCertificateBundleX509ChainFactory : CertificateBundleX509ChainFactory
    {
        // These constants are dictated by the .NET SDK.
        internal const string SubdirectoryName = "trustedroots";
        internal const string CodeSigningFileName = "codesignctl.pem";
        internal const string TimestampingFileName = "timestampctl.pem";

        private static readonly Lazy<string> ThisAssemblyDirectoryPath = new(GetThisAssemblyDirectoryPath, LazyThreadSafetyMode.ExecutionAndPublication);

        private FallbackCertificateBundleX509ChainFactory(X509Certificate2Collection certificates, string filePath)
            : base(certificates, filePath)
        {
        }

        internal static bool TryCreate(
            X509StorePurpose storePurpose,
            string? fileName,
            [NotNullWhen(returnValue: true)] out FallbackCertificateBundleX509ChainFactory? factory)
        {
            factory = null;

            if (string.IsNullOrEmpty(fileName))
            {
                fileName = storePurpose switch
                {
                    X509StorePurpose.CodeSigning => CodeSigningFileName,
                    X509StorePurpose.Timestamping => TimestampingFileName,
                    _ => throw new ArgumentException(Strings.InvalidX509StorePurpose, nameof(storePurpose))
                };
            }

            string fullFilePath = Path.Combine(
                ThisAssemblyDirectoryPath.Value,
                SubdirectoryName,
                fileName);

            if (TryImportFromPemFile(fullFilePath, out X509Certificate2Collection certificates))
            {
                factory = new FallbackCertificateBundleX509ChainFactory(certificates, fullFilePath);

                return true;
            }

            return false;
        }

        private static string GetThisAssemblyDirectoryPath()
        {
            return AppContext.BaseDirectory;
        }
    }
}

#endif