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); }
private static void ValidateTimestampResponseNonce( byte[] nonce, Rfc3161TimestampToken timestampToken) { if (!nonce.SequenceEqual(timestampToken.TokenInfo.GetNonce())) { throw new TimestampException(LogMessage.CreateError( NuGetLogCode.NU3026, string.Format(CultureInfo.CurrentCulture, Strings.TimestampResponseExceptionGeneral, Strings.TimestampFailureNonceMismatch))); } }
/// <summary> /// Logs an error if CLEAR is used with non-CLEAR entries. /// </summary> /// <returns>True if an invalid combination exists.</returns> public static bool LogErrorForClearIfInvalid(IEnumerable <string> values, string projectPath, ILogger logger) { if (HasInvalidClear(values)) { var text = string.Format(CultureInfo.CurrentCulture, Strings.CannotBeUsedWithOtherValues, Clear); var message = LogMessage.CreateError(NuGetLogCode.NU1002, text); message.ProjectPath = projectPath; logger.Log(message); return(true); } return(false); }
public ILogMessage ToLogMessage() { if (Level == LogLevel.Error) { return(LogMessage.CreateError(Code, Message)); } else if (Level == LogLevel.Warning) { return(LogMessage.CreateWarning(Code, Message)); } else { return(new LogMessage(Level, Message)); } }
/// <summary> /// Create a list of certificates in chain order with the leaf first and root last. /// </summary> /// <param name="certificate">The certificate for which a chain should be built.</param> /// <param name="extraStore">A certificate store containing additional certificates necessary /// for chain building.</param> /// <param name="logger">A logger.</param> /// <param name="certificateType">The certificate type.</param> /// <returns>A certificate chain.</returns> /// <remarks>This is intended to be used only during signing and timestamping operations, /// not verification.</remarks> /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="extraStore" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="logger" /> is <c>null</c>.</exception> /// <exception cref="ArgumentException">Thrown if <paramref name="certificateType" /> is undefined.</exception> public static IX509CertificateChain GetCertificateChain( X509Certificate2 certificate, X509Certificate2Collection extraStore, ILogger logger, CertificateType certificateType) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } if (extraStore == null) { throw new ArgumentNullException(nameof(extraStore)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (!Enum.IsDefined(typeof(CertificateType), certificateType)) { throw new ArgumentException(Strings.InvalidArgument, nameof(certificateType)); } using (var chainHolder = new X509ChainHolder()) { var chain = chainHolder.Chain; SetCertBuildChainPolicy( chain.ChainPolicy, extraStore, DateTime.Now, certificateType); chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; if (chain.Build(certificate)) { return(GetCertificateChain(chain)); } X509ChainStatusFlags errorStatusFlags; X509ChainStatusFlags warningStatusFlags; GetChainStatusFlags(certificate, certificateType, out errorStatusFlags, out warningStatusFlags); var fatalStatuses = new List <X509ChainStatus>(); var logCode = certificateType == CertificateType.Timestamp ? NuGetLogCode.NU3028 : NuGetLogCode.NU3018; foreach (var chainStatus in chain.ChainStatus) { if ((chainStatus.Status & errorStatusFlags) != 0) { fatalStatuses.Add(chainStatus); logger.Log(LogMessage.CreateError(logCode, chainStatus.StatusInformation?.Trim())); } else if ((chainStatus.Status & warningStatusFlags) != 0) { logger.Log(LogMessage.CreateWarning(logCode, chainStatus.StatusInformation?.Trim())); } } if (fatalStatuses.Any()) { if (certificateType == CertificateType.Timestamp) { throw new TimestampException(logCode, Strings.CertificateChainValidationFailed); } throw new SignatureException(logCode, Strings.CertificateChainValidationFailed); } return(GetCertificateChain(chain)); } }
public ILogMessage AsLogMessage() { return(LogMessage.CreateError(NuGetLogCode.NU1401, Message)); }
/// <summary> /// Create a list of certificates in chain order with the leaf first and root last. /// </summary> /// <remarks>This must not be used on timestamp certificates as this method does not enforce the requirement /// that timestamps be trusted.</remarks> /// <param name="certificate">The certificate for which a chain should be built.</param> /// <param name="extraStore">A certificate store containing additional certificates necessary /// for chain building.</param> /// <param name="logger">A logger.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="extraStore" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="logger" /> is <c>null</c>.</exception> public static IReadOnlyList <X509Certificate2> GetCertificateChainForSigning( X509Certificate2 certificate, X509Certificate2Collection extraStore, ILogger logger) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } if (extraStore == null) { throw new ArgumentNullException(nameof(extraStore)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } using (var chainHolder = new X509ChainHolder()) { var chain = chainHolder.Chain; SetCertBuildChainPolicy( chain.ChainPolicy, extraStore, DateTime.Now, NuGetVerificationCertificateType.Signature); if (chain.Build(certificate)) { return(GetCertificateListFromChain(chain)); } X509ChainStatusFlags errorStatusFlags; X509ChainStatusFlags warningStatusFlags; GetChainStatusFlagsForSigning(certificate, out errorStatusFlags, out warningStatusFlags); var fatalStatuses = new List <X509ChainStatus>(); foreach (var chainStatus in chain.ChainStatus) { if ((chainStatus.Status & errorStatusFlags) != 0) { fatalStatuses.Add(chainStatus); logger.Log(LogMessage.CreateError(NuGetLogCode.NU3018, chainStatus.StatusInformation?.Trim())); } else if ((chainStatus.Status & warningStatusFlags) != 0) { logger.Log(LogMessage.CreateWarning(NuGetLogCode.NU3018, chainStatus.StatusInformation?.Trim())); } } if (fatalStatuses.Any()) { throw new SignatureException(NuGetLogCode.NU3018, Strings.CertificateChainValidationFailed); } return(GetCertificateListFromChain(chain)); } }
public override ILogMessage AsLogMessage() { return(LogMessage.CreateError(NuGetLogCode.NU1402, Message)); }
/// <summary> /// Timestamps data present in the TimestampRequest. /// </summary> public byte[] TimestampData(TimestampRequest request, ILogger logger, CancellationToken token) { token.ThrowIfCancellationRequested(); if (request == null) { throw new ArgumentNullException(nameof(request)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } // Get the signatureValue from the signerInfo object using (var signatureNativeCms = NativeCms.Decode(request.SignatureValue, detached: false)) { var signatureValueHashByteArray = NativeCms.GetSignatureValueHash( request.TimestampHashAlgorithm, signatureNativeCms); // Allows us to track the request. var nonce = GenerateNonce(); var rfc3161TimestampRequest = new Rfc3161TimestampRequest( signatureValueHashByteArray, request.TimestampHashAlgorithm.ConvertToSystemSecurityHashAlgorithmName(), nonce: nonce, requestSignerCertificates: true); // Request a timestamp // The response status need not be checked here as lower level api will throw if the response is invalid var timestampToken = rfc3161TimestampRequest.SubmitRequest( _timestamperUrl, TimeSpan.FromSeconds(_rfc3161RequestTimeoutSeconds)); // ensure response is for this request ValidateTimestampResponseNonce(nonce, timestampToken); var timestampCms = timestampToken.AsSignedCms(); byte[] timestampByteArray; using (var timestampNativeCms = NativeCms.Decode(timestampCms.Encode(), detached: false)) using (var timestampCertChain = new X509Chain()) { var policy = timestampCertChain.ChainPolicy; policy.ApplicationPolicy.Add(new Oid(Oids.TimeStampingEkuOid)); policy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid; policy.ExtraStore.AddRange(timestampCms.Certificates); policy.RevocationFlag = X509RevocationFlag.ExcludeRoot; policy.RevocationMode = X509RevocationMode.Online; var timestampSignerCertificate = GetTimestampSignerCertificate(timestampCms); if (DateTime.Now < timestampSignerCertificate.NotBefore) { throw new TimestampException(LogMessage.CreateError( NuGetLogCode.NU3025, string.Format(CultureInfo.CurrentCulture, Strings.TimestampCertificateInvalid, $"{Environment.NewLine}{CertificateUtility.X509Certificate2ToString(timestampSignerCertificate)}"))); } if (!timestampCertChain.Build(timestampSignerCertificate)) { throw new TimestampException(LogMessage.CreateError( NuGetLogCode.NU3028, string.Format(CultureInfo.CurrentCulture, Strings.TimestampCertificateChainBuildFailure, $"{Environment.NewLine}{CertificateUtility.X509Certificate2ToString(timestampSignerCertificate)}"))); } // Insert all the certificates into timestampCms InsertTimestampCertChainIntoTimestampCms(timestampCms, timestampCertChain, timestampNativeCms); timestampByteArray = timestampCms.Encode(); } signatureNativeCms.AddTimestamp(timestampByteArray); return(signatureNativeCms.Encode()); } }