| File: Settings\Items\FileClientCertItem.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.Configuration\NuGet.Configuration.csproj (NuGet.Configuration) |
// 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. using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Security.Cryptography.X509Certificates; using System.Xml.Linq; using NuGet.Common; namespace NuGet.Configuration { /// <summary> /// A FileClientCertItem have 4 attributes: /// - [Required] packageSource /// - [Required] path /// - [Optional] password /// - [Optional] clearTextPassword /// </summary> public sealed class FileClientCertItem : ClientCertItem { public FileClientCertItem(string packageSource, string filePath, string? password, bool storePasswordInClearText, string settingsFilePath) : this(packageSource, filePath, password, storePasswordInClearText, GetSettingsFile(settingsFilePath)) { } private static SettingsFile GetSettingsFile(string settingsFilePath) { if (string.IsNullOrWhiteSpace(settingsFilePath)) { throw new ArgumentException(message: Resources.Argument_Cannot_Be_Null_Empty_Or_WhiteSpaceOnly, paramName: nameof(settingsFilePath)); } return new SettingsFile(Path.GetDirectoryName(settingsFilePath)!, Path.GetFileName(settingsFilePath), isMachineWide: false, isReadOnly: false); } internal FileClientCertItem(string packageSource, string filePath, string? password, bool storePasswordInClearText, SettingsFile origin) : base(packageSource) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(filePath)); } Update(filePath, password, storePasswordInClearText); SetOrigin(origin); } internal FileClientCertItem(XElement element, SettingsFile origin) : base(element, origin) { var path = element.Attribute(XName.Get(ConfigurationConstants.PathAttribute))?.Value; var password = element.Attribute(XName.Get(ConfigurationConstants.PasswordAttribute))?.Value; var clearTextPassword = element.Attribute(XName.Get(ConfigurationConstants.ClearTextPasswordAttribute))?.Value; if (string.IsNullOrWhiteSpace(path)) { throw new NuGetConfigurationException(string.Format(CultureInfo.CurrentCulture, Resources.UserSettings_UnableToParseConfigFile, Resources.FileCertItemPathFileNotSet, Origin?.ConfigFilePath ?? "<Config file path>")); } if (!string.IsNullOrWhiteSpace(password) && !string.IsNullOrWhiteSpace(clearTextPassword)) { throw new NuGetConfigurationException(string.Format(CultureInfo.CurrentCulture, Resources.UserSettings_UnableToParseConfigFile, Resources.FileCertItemPasswordAndClearTextPasswordAtSameTime, Origin?.ConfigFilePath ?? "<Config file path>")); } AddAttribute(ConfigurationConstants.PathAttribute, path!); if (!string.IsNullOrWhiteSpace(password)) { AddAttribute(ConfigurationConstants.PasswordAttribute, password!); } if (!string.IsNullOrWhiteSpace(clearTextPassword)) { AddAttribute(ConfigurationConstants.ClearTextPasswordAttribute, clearTextPassword!); } } public override string ElementName => ConfigurationConstants.FileCertificate; public string FilePath => Attributes[ConfigurationConstants.PathAttribute]; public bool IsPasswordIsClearText => Attributes.ContainsKey(ConfigurationConstants.ClearTextPasswordAttribute); public string? Password { get { string? result = null; if (IsPasswordIsClearText) { Attributes.TryGetValue(ConfigurationConstants.ClearTextPasswordAttribute, out result); } else { if (Attributes.TryGetValue(ConfigurationConstants.PasswordAttribute, out var encryptedPassword)) { try { result = EncryptionUtility.DecryptString(encryptedPassword); } catch (Exception e) { throw new NuGetConfigurationException(string.Format(CultureInfo.CurrentCulture, Resources.FileCertItemPasswordCannotBeDecrypted, PackageSource), e); } } } return result; } } protected override IReadOnlyCollection<string> AllowedAttributes { get; } = new HashSet<string>(new[] { ConfigurationConstants.PackageSourceAttribute, ConfigurationConstants.PathAttribute, ConfigurationConstants.PasswordAttribute, ConfigurationConstants.ClearTextPasswordAttribute }); protected override IReadOnlyCollection<string> RequiredAttributes { get; } = new HashSet<string>(new[] { ConfigurationConstants.PackageSourceAttribute, ConfigurationConstants.PathAttribute }); internal override XNode AsXNode() { if (Node is XElement) { return Node; } var element = new XElement(ElementName); foreach (KeyValuePair<string, string> attr in Attributes) { element.SetAttributeValue(attr.Key, attr.Value); } return element; } public override SettingBase Clone() { return new FileClientCertItem(PackageSource, FilePath, Password, IsPasswordIsClearText, Origin!); } public override IEnumerable<X509Certificate> Search() { var filePath = FindAbsoluteFilePath(); if (string.IsNullOrWhiteSpace(filePath)) { throw new NuGetConfigurationException(string.Format(CultureInfo.CurrentCulture, Resources.FileCertItemPathFileNotExist)); } #if NET9_0_OR_GREATER return new[] { string.IsNullOrWhiteSpace(Password) ? X509CertificateLoader.LoadPkcs12FromFile(filePath, null) : X509CertificateLoader.LoadPkcs12FromFile(filePath, Password) }; #else return new[] { string.IsNullOrWhiteSpace(Password) ? new X509Certificate2(filePath) : new X509Certificate2(filePath, Password) }; #endif } public void Update(string filePath, string? password, bool storePasswordInClearText) { if (!string.IsNullOrWhiteSpace(filePath)) { AddOrUpdateAttribute(ConfigurationConstants.PathAttribute, filePath); } if (!string.IsNullOrWhiteSpace(password)) { if (storePasswordInClearText) { AddOrUpdateAttribute(ConfigurationConstants.ClearTextPasswordAttribute, password); UpdateAttribute(ConfigurationConstants.PasswordAttribute, null); } else { var encryptedPassword = EncryptionUtility.EncryptString(password!); AddOrUpdateAttribute(ConfigurationConstants.PasswordAttribute, encryptedPassword); UpdateAttribute(ConfigurationConstants.ClearTextPasswordAttribute, null); } } } private string? FindAbsoluteFilePath() { var originalValue = FilePath; if (File.Exists(originalValue)) { //File was found by absolute file path return originalValue; } if (PathValidator.IsValidRelativePath(originalValue) && Origin != null) { //File was found by relative to config file path var relativeToConfigFilePath = PathUtility.GetAbsolutePath(PathUtility.EnsureTrailingSlash(Origin.DirectoryPath), originalValue); if (File.Exists(relativeToConfigFilePath)) { return relativeToConfigFilePath; } } //File was not found return null; } } }