private static X509Certificate2Collection LoadCertificateFromStore(CertificateSourceOptions options)
        {
            X509Certificate2Collection resultCollection = null;
            var store = new X509Store(options.StoreName, options.StoreLocation);

            OpenStore(store);

            // Passing true for validOnly seems like a good idea; it would filter out invalid certificates.
            // However, "invalid certificates" is a broad category that includes untrusted self-issued certificates.
            // Untrusted self-issued certificates are permitted at signing time, so we must perform certificate
            // validity checks ourselves.
            const bool validOnly = false;

            if (!string.IsNullOrEmpty(options.Fingerprint))
            {
                resultCollection = store.Certificates.Find(X509FindType.FindByThumbprint, options.Fingerprint, validOnly);
            }
            else if (!string.IsNullOrEmpty(options.SubjectName))
            {
                resultCollection = store.Certificates.Find(X509FindType.FindBySubjectName, options.SubjectName, validOnly);
            }

#if IS_DESKTOP
            store.Close();
#endif

            resultCollection = resultCollection ?? new X509Certificate2Collection();
            resultCollection = GetValidCertificates(resultCollection);

            return(resultCollection);
        }
Esempio n. 2
0
        private static async Task <X509Certificate2> GetCertificateAsync(SignArgs signArgs)
        {
            var certFindOptions = new CertificateSourceOptions()
            {
                CertificatePath     = signArgs.CertificatePath,
                CertificatePassword = signArgs.CertificatePassword,
                Fingerprint         = signArgs.CertificateFingerprint,
                StoreLocation       = signArgs.CertificateStoreLocation,
                StoreName           = signArgs.CertificateStoreName,
                SubjectName         = signArgs.CertificateSubjectName,
                NonInteractive      = signArgs.NonInteractive,
                PasswordProvider    = signArgs.PasswordProvider,
                Token = signArgs.Token
            };

            // get matching certificates
            var matchingCertCollection = await CertificateProvider.GetCertificatesAsync(certFindOptions);

            if (matchingCertCollection.Count > 1)
            {
#if IS_DESKTOP
                if (signArgs.NonInteractive || !RuntimeEnvironmentHelper.IsWindows)
                {
                    // if on non-windows os or in non interactive mode - display the certs and error out
                    signArgs.Logger.LogInformation(CertificateUtility.X509Certificate2CollectionToString(matchingCertCollection, HashAlgorithmName.SHA256));
                    throw new SignCommandException(
                              LogMessage.CreateError(NuGetLogCode.NU3001,
                                                     string.Format(Strings.SignCommandMultipleCertException,
                                                                   nameof(SignArgs.CertificateFingerprint))));
                }
                else
                {
                    // Else launch UI to select
                    matchingCertCollection = X509Certificate2UI.SelectFromCollection(
                        FilterCodeSigningCertificates(matchingCertCollection),
                        Strings.SignCommandDialogTitle,
                        Strings.SignCommandDialogMessage,
                        X509SelectionFlag.SingleSelection);
                }
#else
                // if on non-windows os or in non interactive mode - display and error out
                signArgs.Logger.LogError(CertificateUtility.X509Certificate2CollectionToString(matchingCertCollection, HashAlgorithmName.SHA256));

                throw new SignCommandException(
                          LogMessage.CreateError(NuGetLogCode.NU3001,
                                                 string.Format(Strings.SignCommandMultipleCertException,
                                                               nameof(SignArgs.CertificateFingerprint))));
#endif
            }

            if (matchingCertCollection.Count == 0)
            {
                throw new SignCommandException(
                          LogMessage.CreateError(NuGetLogCode.NU3001,
                                                 Strings.SignCommandNoCertException));
            }

            return(matchingCertCollection[0]);
        }
        /// <summary>
        /// Looks for X509Certificates using the CertificateSourceOptions.
        /// Throws an InvalidOperationException if the option specifies a CertificateFilePath with invalid password.
        /// </summary>
        /// <param name="options">CertificateSourceOptions to be used while searching for the certificates.</param>
        /// <returns>An X509Certificate2Collection object containing matching certificates.
        /// If no matching certificates are found then it returns an empty collection.</returns>
        public static async Task <X509Certificate2Collection> GetCertificatesAsync(CertificateSourceOptions options)
        {
            // check certificate path
            var resultCollection = new X509Certificate2Collection();

            if (!string.IsNullOrEmpty(options.CertificatePath))
            {
                try
                {
                    var cert = await LoadCertificateFromFileAsync(options);

                    resultCollection = new X509Certificate2Collection(cert);
                }
                catch (CryptographicException ex)
                {
                    switch (ex.HResult)
                    {
                    case ERROR_INVALID_PASSWORD_HRESULT:
                    case OPENSSL_PKCS12_R_MAC_VERIFY_FAILURE:
                        throw new SignCommandException(
                                  LogMessage.CreateError(NuGetLogCode.NU3001,
                                                         string.Format(CultureInfo.CurrentCulture,
                                                                       Strings.SignCommandInvalidPasswordException,
                                                                       options.CertificatePath,
                                                                       nameof(options.CertificatePassword))));

                    case ERROR_FILE_NOT_FOUND_HRESULT:
                    case OPENSSL_BIO_R_NO_SUCH_FILE:
                        throw new SignCommandException(
                                  LogMessage.CreateError(NuGetLogCode.NU3001,
                                                         string.Format(CultureInfo.CurrentCulture,
                                                                       Strings.SignCommandCertificateFileNotFound,
                                                                       options.CertificatePath)));

                    case CRYPT_E_NO_MATCH_HRESULT:
                    case OPENSSL_ERR_R_NESTED_ASN1_ERROR:
                        throw new SignCommandException(
                                  LogMessage.CreateError(NuGetLogCode.NU3001,
                                                         string.Format(CultureInfo.CurrentCulture,
                                                                       Strings.SignCommandInvalidCertException,
                                                                       options.CertificatePath)));

                    default:
                        throw;
                    }
                }
            }
            else
            {
                resultCollection = LoadCertificateFromStore(options);
            }

            return(resultCollection);
        }
Esempio n. 4
0
        private static X509Certificate2Collection LoadCertificateFromStore(CertificateSourceOptions options)
        {
            var resultCollection = new X509Certificate2Collection();
            var store            = new X509Store(options.StoreName, options.StoreLocation);

            OpenStore(store);

            if (!string.IsNullOrEmpty(options.Fingerprint))
            {
                resultCollection = store.Certificates.Find(X509FindType.FindByThumbprint, options.Fingerprint, validOnly: true);
            }
            else if (!string.IsNullOrEmpty(options.SubjectName))
            {
                resultCollection = store.Certificates.Find(X509FindType.FindBySubjectName, options.SubjectName, validOnly: true);
            }

#if IS_DESKTOP
            store.Close();
#endif
            return(resultCollection);
        }
        private static async Task <X509Certificate2> LoadCertificateFromFileAsync(CertificateSourceOptions options)
        {
            X509Certificate2 cert;

            if (!string.IsNullOrEmpty(options.CertificatePassword))
            {
                cert = new X509Certificate2(options.CertificatePath, options.CertificatePassword); // use the password if the user provided it.
            }
            else
            {
#if IS_DESKTOP
                try
                {
                    cert = new X509Certificate2(options.CertificatePath);
                }
                catch (CryptographicException ex)
                {
                    // prompt user for password if needed
                    if (ex.HResult == ERROR_INVALID_PASSWORD_HRESULT &&
                        !options.NonInteractive)
                    {
                        using (var password = await options.PasswordProvider.GetPassword(options.CertificatePath, options.Token))
                        {
                            cert = new X509Certificate2(options.CertificatePath, password);
                        }
                    }
                    else
                    {
                        throw;
                    }
                }
#else
                cert = new X509Certificate2(options.CertificatePath);
#endif
            }

            return(cert);
        }