Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
CertificateProvider.cs3566 linesDownload Raw Back to security
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#if !UNIX5 6using System;7using System.Collections;8using System.Collections.Generic;9using System.Collections.ObjectModel;10using System.Diagnostics;11using System.Diagnostics.CodeAnalysis;12using System.Globalization;13using System.IO;14using System.Management.Automation;15using System.Management.Automation.Host;16using System.Management.Automation.Internal;17using System.Management.Automation.Provider;18using System.Runtime.InteropServices;19using System.Security;20using System.Security.Cryptography;21using System.Security.Cryptography.X509Certificates;22using System.Text.RegularExpressions;23using System.Xml;24using System.Xml.XPath;25 26using Dbg = System.Management.Automation;27using DWORD = System.UInt32;28using Runspaces = System.Management.Automation.Runspaces;29using SMASecurity = System.Management.Automation.Security;30 31namespace Microsoft.PowerShell.Commands32{33    /// <summary>34    /// Defines the Certificate Provider dynamic parameters.35    /// We only support one dynamic parameter for Win 7 and earlier:36    /// CodeSigningCert37    /// If provided, we only return certificates valid for signing code or38    /// scripts.39    /// </summary>40    internal sealed class CertificateProviderDynamicParameters41    {42        /// <summary>43        /// Gets or sets a switch that controls whether we only return44        /// code signing certs.45        /// </summary>46        [Parameter]47        public SwitchParameter CodeSigningCert48        {49            get { return _codeSigningCert; }50 51            set { _codeSigningCert = value; }52        }53 54        private SwitchParameter _codeSigningCert = new();55 56        /// <summary>57        /// Gets or sets a filter that controls whether we only return58        /// data encipherment certs.59        /// </summary>60        [Parameter]61        public SwitchParameter DocumentEncryptionCert62        {63            get;64            set;65        }66 67        /// <summary>68        /// Gets or sets a filter that controls whether we only return69        /// server authentication certs.70        /// </summary>71        [Parameter]72        public SwitchParameter SSLServerAuthentication73        {74            get;75            set;76        }77 78        /// <summary>79        /// Gets or sets a filter by DNSName.80        /// Expected content is a single DNS Name that may start and/or end81        /// with '*': "contoso.com" or "*toso.c*".82        /// All WildcardPattern class features supported.83        /// </summary>84        [Parameter]85        public string DnsName86        {87            get;88            set;89        }90 91        /// <summary>92        /// Gets or sets a filter by EKU.93        /// Expected content is one or more OID strings:94        /// "1.3.6.1.5.5.7.3.1", "*Server*", etc.95        /// For a cert to match, it must be valid for all listed OIDs.96        /// All WildcardPattern class features supported.97        /// </summary>98        [Parameter]99        public string[] Eku100        {101            get;102            set;103        }104 105        /// <summary>106        /// Gets or sets a filter by the number of valid days.107        /// Expected content is a non-negative integer.108        /// "0" matches all certs that have already expired.109        /// "1" matches all certs that are currently valid and will expire110        /// by next day (local time).111        /// </summary>112        [Parameter]113        [ValidateRange(ValidateRangeKind.NonNegative)]114        public int ExpiringInDays115        {116            get;117            set;118        } = -1;119    }120 121    /// <summary>122    /// Defines the type of DNS string123    /// The structure contains punycode name and unicode name.124    /// </summary>125    [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]126    public readonly struct DnsNameRepresentation127    {128        /// <summary>129        /// Punycode version of DNS name.130        /// </summary>131        private readonly string _punycodeName;132 133        /// <summary>134        /// Unicode version of DNS name.135        /// </summary>136        private readonly string _unicodeName;137 138        /// <summary>139        /// Ambiguous constructor of a DnsNameRepresentation.140        /// </summary>141        public DnsNameRepresentation(string inputDnsName)142        {143            _punycodeName = inputDnsName;144            _unicodeName = inputDnsName;145        }146 147        /// <summary>148        /// Specific constructor of a DnsNameRepresentation.149        /// </summary>150        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Punycode")]151        public DnsNameRepresentation(152            string inputPunycodeName,153            string inputUnicodeName)154        {155            _punycodeName = inputPunycodeName;156            _unicodeName = inputUnicodeName;157        }158 159        /// <summary>160        /// Value comparison.161        /// </summary>162        public bool Equals(DnsNameRepresentation dnsName)163        {164            bool match = false;165 166            if (_unicodeName != null && dnsName._unicodeName != null)167            {168                if (string.Equals(169                            _unicodeName,170                            dnsName._unicodeName,171                            StringComparison.OrdinalIgnoreCase))172                {173                    match = true;174                }175            }176            else if (_unicodeName == null && dnsName._unicodeName == null)177            {178                match = true;179            }180 181            return match;182        }183 184        /// <summary>185        /// Get property of Punycode.186        /// </summary>187        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Punycode")]188        public string Punycode189        {190            get191            {192                return _punycodeName;193            }194        }195 196        /// <summary>197        /// Get property of Unicode.198        /// </summary>199        public string Unicode200        {201            get202            {203                return _unicodeName;204            }205        }206 207        /// <summary>208        /// Get display string.209        /// </summary>210        public override string ToString()211        {212            // Use case sensitive comparison here.213            // We don't ever expect to see the punycode and unicode strings214            // to differ only by upper/lower case.  If they do, that's really215            // a code bug, and the effect is to just display both strings.216 217            return string.Equals(_punycodeName, _unicodeName, StringComparison.Ordinal)218                ? _punycodeName219                : _unicodeName + " (" + _punycodeName + ")";220        }221    }222 223    /// <summary>224    /// Defines the Certificate Provider remove-item dynamic parameters.225    ///226    /// Currently, we only support one dynamic parameter: DeleteKey227    /// If provided, we will delete the private key when we remove a certificate.228    /// </summary>229    internal sealed class ProviderRemoveItemDynamicParameters230    {231        /// <summary>232        /// Switch that controls whether we should delete private key233        /// when remove a certificate.234        /// </summary>235        [Parameter]236        public SwitchParameter DeleteKey237        {238            get239            {240                {241                    return _deleteKey;242                }243            }244 245            set246            {247                {248                    _deleteKey = value;249                }250            }251        }252 253        private SwitchParameter _deleteKey = new();254    }255 256    /// <summary>257    /// Defines the safe handle class for native cert store handles,258    /// HCERTSTORE.259    /// </summary>260    internal sealed class CertificateStoreHandle : SafeHandle261    {262        public CertificateStoreHandle() : base(IntPtr.Zero, true)263        {264            return;265        }266 267        public override bool IsInvalid268        {269            get { return handle == IntPtr.Zero; }270        }271 272        protected override bool ReleaseHandle()273        {274            bool fResult = false;275 276            if (handle != IntPtr.Zero)277            {278                fResult = SMASecurity.NativeMethods.CertCloseStore(handle, 0);279                handle = IntPtr.Zero;280            }281 282            return fResult;283        }284 285        public IntPtr Handle286        {287            get { return handle; }288 289            set { handle = value; }290        }291    }292 293    /// <summary>294    /// Defines the Certificate Provider store handle class.295    /// </summary>296    internal sealed class X509NativeStore297    {298        // #region tracer299 300        /// <summary>301        /// Initializes a new instance of the X509NativeStore class.302        /// </summary>303        public X509NativeStore(X509StoreLocation StoreLocation, string StoreName)304        {305            _storeLocation = StoreLocation;306            _storeName = StoreName;307        }308 309        public void Open(bool includeArchivedCerts)310        {311            if (_storeHandle != null && _archivedCerts != includeArchivedCerts)312            {313                _storeHandle = null;        // release the old handle314            }315 316            if (_storeHandle == null)317            {318                _valid = false;319                _open = false;320 321                SMASecurity.NativeMethods.CertOpenStoreFlags StoreFlags =322                    SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_STORE_SHARE_STORE_FLAG |323                    SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_STORE_SHARE_CONTEXT_FLAG |324                    SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_STORE_OPEN_EXISTING_FLAG |325                    SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_STORE_MAXIMUM_ALLOWED_FLAG;326 327                if (includeArchivedCerts)328                {329                    StoreFlags |= SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_STORE_ENUM_ARCHIVED_FLAG;330                }331 332                switch (_storeLocation.Location)333                {334                    case StoreLocation.LocalMachine:335                        StoreFlags |= SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_SYSTEM_STORE_LOCAL_MACHINE;336                        break;337 338                    case StoreLocation.CurrentUser:339                        StoreFlags |= SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_SYSTEM_STORE_CURRENT_USER;340                        break;341 342                    default:343                        // ThrowItemNotFound(storeLocation.ToString(), CertificateProviderItem.StoreLocation);344                        break;345                }346 347                IntPtr hCertStore = SMASecurity.NativeMethods.CertOpenStore(348                                SMASecurity.NativeMethods.CertOpenStoreProvider.CERT_STORE_PROV_SYSTEM,349                                SMASecurity.NativeMethods.CertOpenStoreEncodingType.X509_ASN_ENCODING,350                                IntPtr.Zero,  // hCryptProv351                                StoreFlags,352                                _storeName);353                if (hCertStore == IntPtr.Zero)354                {355                    throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());356                }357 358                _storeHandle = new CertificateStoreHandle();359                _storeHandle.Handle = hCertStore;360 361                // we only do CertControlStore for stores other than UserDS362                if (!string.Equals(363                                _storeName,364                                "UserDS",365                                StringComparison.OrdinalIgnoreCase))366                {367                    if (!SMASecurity.NativeMethods.CertControlStore(368                                _storeHandle.Handle,369                                0,370                                SMASecurity.NativeMethods.CertControlStoreType.CERT_STORE_CTRL_AUTO_RESYNC,371                                IntPtr.Zero))372                    {373                        _storeHandle = null;374                        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());375                    }376                }377 378                _valid = true;379                _open = true;380                _archivedCerts = includeArchivedCerts;381            }382        }383 384        public IntPtr GetFirstCert()385        {386            return GetNextCert(IntPtr.Zero);387        }388 389        public IntPtr GetNextCert(IntPtr certContext)390        {391            if (!_open)392            {393                throw Marshal.GetExceptionForHR(394                                    SMASecurity.NativeMethods.CRYPT_E_NOT_FOUND);395            }396 397            if (Valid)398            {399                certContext = SMASecurity.NativeMethods.CertEnumCertificatesInStore(400                                                    _storeHandle.Handle,401                                                    certContext);402            }403            else404            {405                certContext = IntPtr.Zero;406            }407 408            return certContext;409        }410 411        public IntPtr GetCertByName(string Name)412        {413            IntPtr certContext = IntPtr.Zero;414 415            if (!_open)416            {417                throw Marshal.GetExceptionForHR(418                                    SMASecurity.NativeMethods.CRYPT_E_NOT_FOUND);419            }420 421            if (Valid)422            {423                if (DownLevelHelper.HashLookupSupported())424                {425                    certContext = SMASecurity.NativeMethods.CertFindCertificateInStore(426                            _storeHandle.Handle,427                            SMASecurity.NativeMethods.CertOpenStoreEncodingType.X509_ASN_ENCODING,428                            0,                                // dwFindFlags429                            SMASecurity.NativeMethods.CertFindType.CERT_FIND_HASH_STR,430                            Name,431                            IntPtr.Zero);                     // pPrevCertContext432                }433                else434                {435                    //436                    // the pre-Win8 CAPI2 code does not provide an easy way437                    // to directly access a specific certificate.438                    // We have to iterate through all certs to find439                    // what we want.440                    //441 442                    while (true)443                    {444                        certContext = GetNextCert(certContext);445                        if (certContext == IntPtr.Zero)446                        {447                            break;448                        }449 450                        X509Certificate2 cert = new(certContext);451                        if (string.Equals(452                                    cert.Thumbprint,453                                    Name,454                                    StringComparison.OrdinalIgnoreCase))455                        {456                            break;457                        }458                    }459                }460            }461 462            return certContext;463        }464 465        public void FreeCert(IntPtr certContext)466        {467            SMASecurity.NativeMethods.CertFreeCertificateContext(certContext);468        }469 470        /// <summary>471        /// Native IntPtr store handle.472        /// </summary>473        public IntPtr StoreHandle474        {475            get476            {477                return _storeHandle.Handle;478            }479        }480 481        /// <summary>482        /// X509StoreLocation store location.483        /// </summary>484        public X509StoreLocation Location485        {486            get487            {488                return _storeLocation;489            }490        }491 492        /// <summary>493        /// String store name.494        /// </summary>495        public string StoreName496        {497            get498            {499                return _storeName;500            }501        }502 503        /// <summary>504        /// True if a real store is open.505        /// </summary>506        public bool Valid507        {508            get509            {510                return _valid;511            }512        }513 514        private bool _archivedCerts = false;515        private readonly X509StoreLocation _storeLocation = null;516        private readonly string _storeName = null;517        private CertificateStoreHandle _storeHandle = null;518        private bool _valid = false;519        private bool _open = false;520    }521 522    /// <summary>523    /// Defines the types of items524    /// supported by the certificate provider.525    /// </summary>526    internal enum CertificateProviderItem527    {528        /// <summary>529        /// An unknown item.530        /// </summary>531        Unknown,532 533        /// <summary>534        /// An X509 Certificate.535        /// </summary>536        Certificate,537 538        /// <summary>539        /// A certificate store location.540        /// For example, cert:\CurrentUser.541        /// </summary>542        Store,543 544        /// <summary>545        /// A certificate store.546        /// For example, cert:\CurrentUser\My.547        /// </summary>548        StoreLocation549    }550 551    /// <summary>552    /// Defines the implementation of a Certificate Store Provider.  This provider553    /// allows for stateless namespace navigation of the computer's certificate554    /// store.555    /// </summary>556    [CmdletProvider("Certificate", ProviderCapabilities.ShouldProcess)]557    [OutputType(typeof(string), typeof(PathInfo), ProviderCmdlet = ProviderCmdlet.ResolvePath)]558    [OutputType(typeof(PathInfo), ProviderCmdlet = ProviderCmdlet.PushLocation)]559    [OutputType(typeof(PathInfo), ProviderCmdlet = ProviderCmdlet.PopLocation)]560    [OutputType(typeof(Microsoft.PowerShell.Commands.X509StoreLocation), typeof(X509Certificate2), ProviderCmdlet = ProviderCmdlet.GetItem)]561    [OutputType(typeof(X509Store), typeof(X509Certificate2), ProviderCmdlet = ProviderCmdlet.GetChildItem)]562    public sealed class CertificateProvider : NavigationCmdletProvider, ICmdletProviderSupportsHelp563    {564        #region tracer565 566        /// <summary>567        /// Tracer for certificate provider.568        /// </summary>569        [TraceSource("CertificateProvider",570                      "The core command provider for certificates")]571        private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("CertificateProvider",572                      "The core command provider for certificates");573 574        #endregion tracer575 576        /// <summary>577        /// Indicate if we already have attempted to load the PKI module.578        /// </summary>579        private bool _hasAttemptedToLoadPkiModule = false;580 581        /// <summary>582        /// Lock that guards access to the following static members583        /// -- storeLocations584        /// -- pathCache.585        /// </summary>586        private static readonly object s_staticLock = new();587 588        /// <summary>589        /// List of store locations. They do not change once initialized.590        ///591        /// Synchronized on staticLock.592        /// </summary>593        private static List<X509StoreLocation> s_storeLocations = null;594 595        /// <summary>596        /// Cache that stores paths and their associated objects.597        ///598        /// key is full path to store-location/store/certificate599        /// value is X509StoreLocation/X509NativeStore/X509Certificate2 object600        ///601        /// Synchronized on staticLock.602        /// </summary>603        private static Hashtable s_pathCache = null;604 605        /// <summary>606        /// We allow either / or \ to be the path separator.607        /// </summary>608        private static readonly char[] s_pathSeparators = new char[] { '/', '\\' };609 610        /// <summary>611        /// Regex pattern that defines a valid cert path.612        /// </summary>613        private const string certPathPattern = @"^\\((?<StoreLocation>CurrentUser|LocalMachine)(\\(?<StoreName>[a-zA-Z]+)(\\(?<Thumbprint>[0-9a-f]{40}))?)?)?$";614 615        /// <summary>616        /// Cache the store handle to avoid repeated CertOpenStore calls.617        /// </summary>618        private static X509NativeStore s_storeCache = null;619 620        /// <summary>621        /// On demand create the Regex to avoid a hit to startup perf.622        /// </summary>623        /// <remarks>624        /// Note, its OK that staticLock is being used here because only625        /// IsValidPath is calling this static property so we shouldn't626        /// have any deadlocks due to other locked static members calling627        /// this property.628        /// </remarks>629        private static Regex s_certPathRegex = null;630 631        private static Regex CertPathRegex632        {633            get634            {635                lock (s_staticLock)636                {637                    if (s_certPathRegex == null)638                    {639                        const RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled;640                        s_certPathRegex = new Regex(certPathPattern, options);641                    }642                }643 644                return s_certPathRegex;645            }646        }647 648        /// <summary>649        /// Initializes a new instance of the CertificateProvider class.650        /// This initializes the default certificate store locations.651        /// </summary>652        public CertificateProvider()653        {654            //655            // initialize storeLocations list and also update the cache656            //657            lock (s_staticLock)658            {659                if (s_storeLocations == null)660                {661                    s_pathCache = new Hashtable(StringComparer.OrdinalIgnoreCase);662                    s_storeLocations =663                        new List<X509StoreLocation>();664 665                    //666                    // create and cache CurrentUser store-location667                    //668                    X509StoreLocation user = new(StoreLocation.CurrentUser);669                    s_storeLocations.Add(user);670                    AddItemToCache(nameof(StoreLocation.CurrentUser),671                                  user);672 673                    //674                    // create and cache LocalMachine store-location675                    //676                    X509StoreLocation machine = new(StoreLocation.LocalMachine);677                    s_storeLocations.Add(machine);678                    AddItemToCache(nameof(StoreLocation.LocalMachine),679                                   machine);680 681                    AddItemToCache(string.Empty, s_storeLocations);682                }683            }684        }685 686        /// <summary>687        /// Removes an item at the specified path.688        /// </summary>689        /// <param name="path">690        /// The path of the item to remove.691        /// </param>692        /// <param name="recurse">693        /// Recursively remove.694        /// </param>695        /// <returns>696        /// Nothing.697        /// </returns>698        /// <exception cref="System.ArgumentException">699        ///     path is null or empty.700        ///     destination is null or empty.701        /// </exception>702        protected override void RemoveItem(703                                string path,704                                bool recurse)705        {706            path = NormalizePath(path);707            bool isContainer = false;708            bool fDeleteKey = false;709 710            object outObj = GetItemAtPath(path, false, out isContainer);711            string[] pathElements = GetPathElements(path);712 713            bool fUserContext = string.Equals(pathElements[0], "CurrentUser", StringComparison.OrdinalIgnoreCase);714 715            // isContainer = true means not a valid certificate716 717            // if source store is user root store and UI is not allowed718            // we raise invalid operation719            if (DetectUIHelper.GetOwnerWindow(Host) == IntPtr.Zero && fUserContext &&720                 string.Equals(pathElements[1], "ROOT", StringComparison.OrdinalIgnoreCase))721            {722                string message = CertificateProviderStrings.UINotAllowed;723                const string errorId = "UINotAllowed";724                ThrowInvalidOperation(errorId, message);725            }726 727            if (DynamicParameters != null && DynamicParameters is ProviderRemoveItemDynamicParameters dp)728            {729                if (dp.DeleteKey)730                {731                    fDeleteKey = true;732                }733            }734 735            if (isContainer)736            {737                if (pathElements.Length == 2) // is a store738                {739                    // not support user context740                    if (fUserContext)741                    {742                        string message = CertificateProviderStrings.CannotDeleteUserStore;743                        const string errorId = "CannotDeleteUserStore";744                        ThrowInvalidOperation(errorId, message);745                    }746 747                    RemoveCertStore(pathElements[1], fDeleteKey, path);748                    return;749                }750                else // other container than a store751                {752                    string message = CertificateProviderStrings.CannotRemoveContainer;753                    const string errorId = "CannotRemoveContainer";754                    ThrowInvalidOperation(errorId, message);755                }756            }757            else // certificate758            {759                // do remove760                X509Certificate2 certificate = outObj as X509Certificate2;761                RemoveCertItem(certificate, fDeleteKey, !fUserContext, path);762                return;763            }764        }765 766        /// <summary>767        /// Gets the dynamic parameters for remove-item on the Certificate768        /// Provider.  We currently only support one dynamic parameter,769        /// "DeleteKey," that delete private key when we delete a certificate.770        /// </summary>771        /// <param name="path">772        /// If the path was specified on the command line, this is the path773        /// to the item for which to get the dynamic parameters.774        /// </param>775        /// <param name="recurse">776        /// Ignored.777        /// </param>778        /// <returns>779        /// An object that has properties and fields decorated with780        /// parsing attributes similar to a cmdlet class.781        /// </returns>782        protected override object RemoveItemDynamicParameters(string path, bool recurse)783        {784            return new ProviderRemoveItemDynamicParameters();785        }786 787        /// <summary>788        /// Moves an item at the specified path to the given destination.789        /// </summary>790        /// <param name="path">791        /// The path of the item to move.792        /// </param>793        /// <param name="destination">794        /// The path of the destination.795        /// </param>796        /// <returns>797        /// Nothing.  Moved items are written to the context's pipeline.798        /// </returns>799        /// <exception cref="System.ArgumentException">800        ///     path is null or empty.801        ///     destination is null or empty.802        /// </exception>803        protected override void MoveItem(804                                string path,805                                string destination)806        {807            // normalize path808            path = NormalizePath(path);809            destination = NormalizePath(destination);810 811            // get elements from the path812            string[] pathElements = GetPathElements(path);813            string[] destElements = GetPathElements(destination);814 815            bool isContainer = false;816            object cert = GetItemAtPath(path, false, out isContainer);817 818            //819            // isContainer = true; means an invalid path820            //821            if (isContainer)822            {823                string message = CertificateProviderStrings.CannotMoveContainer;824                const string errorId = "CannotMoveContainer";825                ThrowInvalidOperation(errorId, message);826            }827 828            if (destElements.Length != 2) // not a store829            {830                // if the destination leads to the same thumbprint831                if (destElements.Length == 3 &&832                   (string.Equals(pathElements[2], destElements[2], StringComparison.OrdinalIgnoreCase)))833                {834                    // in this case we think of destination path as valid835                    // and strip the thumbprint part836                    destination = Path.GetDirectoryName(destination);837                }838                else839                {840                    string message = CertificateProviderStrings.InvalidDestStore;841                    const string errorId = "InvalidDestStore";842                    ThrowInvalidOperation(errorId, message);843                }844            }845 846            // the second element is store location847            // we do not allow cross context move848            // we do not allow the destination store is the same as source849 850            if (!string.Equals(pathElements[0], destElements[0], StringComparison.OrdinalIgnoreCase))851            {852                string message = CertificateProviderStrings.CannotMoveCrossContext;853                const string errorId = "CannotMoveCrossContext";854                ThrowInvalidOperation(errorId, message);855            }856 857            if (string.Equals(pathElements[1], destElements[1], StringComparison.OrdinalIgnoreCase))858            {859                string message = CertificateProviderStrings.CannotMoveToSameStore;860                const string errorId = "CannotMoveToSameStore";861                ThrowInvalidOperation(errorId, message);862            }863 864            // if source or destination store is user root store and UI is not allowed865            // we raise invalid operation866            if (DetectUIHelper.GetOwnerWindow(Host) == IntPtr.Zero)867            {868                if ((string.Equals(pathElements[0], "CurrentUser", StringComparison.OrdinalIgnoreCase) &&869                     string.Equals(pathElements[1], "ROOT", StringComparison.OrdinalIgnoreCase)) ||870                     (string.Equals(destElements[0], "CurrentUser", StringComparison.OrdinalIgnoreCase) &&871                     string.Equals(destElements[1], "ROOT", StringComparison.OrdinalIgnoreCase)))872                {873                    string message = CertificateProviderStrings.UINotAllowed;874                    const string errorId = "UINotAllowed";875                    ThrowInvalidOperation(errorId, message);876                }877            }878 879            if (cert != null) // we get cert880            {881                // get destination store882                bool isDestContainer = false;883                object store = GetItemAtPath(destination, false, out isDestContainer);884 885                X509Certificate2 certificate = cert as X509Certificate2;886 887                if (store is X509NativeStore certstore)888                {889                    certstore.Open(true);890 891                    string action = CertificateProviderStrings.Action_Move;892                    string resource = string.Format(893                                          CultureInfo.CurrentCulture,894                                          CertificateProviderStrings.MoveItemTemplate,895                                          path,896                                          destination);897                    if (ShouldProcess(resource, action))898                    {899                        DoMove(destination, certificate, certstore, path);900                    }901                }902            }903            else904            {905                ThrowItemNotFound(path, CertificateProviderItem.Certificate);906            }907        }908 909        /// <summary>910        /// Creates a certificate store with the given path.911        /// </summary>912        /// <remarks>913        /// New-Item doesn't go through the method "ItemExists". But for the914        /// CertificateProvider, New-Item can create an X509Store and return915        /// it, and the user can access the certificates within the store via its916        /// property "Certificates". We want the extra new properties of the917        /// X509Certificate2 objects to be shown to the user, so we also need918        /// to import the PKI module in this method, if we haven't tried it yet.919        /// </remarks>920        /// <param name="path">921        /// The path of the certificate store to create.922        /// </param>923        /// <param name="type">924        /// Ignored.925        /// Only support store.926        /// </param>927        /// <param name="value">928        /// Ignored929        /// </param>930        /// <returns>931        /// Nothing.  The new certificate store object is932        /// written to the context's pipeline.933        /// </returns>934        /// <exception cref="System.ArgumentException">935        ///     path is null or empty.936        /// </exception>937        protected override void NewItem(938                string path,939                string type,940                object value)941        {942            if (!_hasAttemptedToLoadPkiModule)943            {944                // Attempt to load the PKI module if we haven't tried yet945                AttemptToImportPkiModule();946            }947 948            path = NormalizePath(path);949 950            // get the elements from the path951            string[] pathElements = GetPathElements(path);952 953            // only support creating store954            if (pathElements.Length != 2)955            {956                string message = CertificateProviderStrings.CannotCreateItem;957                const string errorId = "CannotCreateItem";958                ThrowInvalidOperation(errorId, message);959            }960 961            bool fUserContext = string.Equals(pathElements[0], "CurrentUser", StringComparison.OrdinalIgnoreCase);962 963            // not support user context964            if (fUserContext)965            {966                string message = CertificateProviderStrings.CannotCreateUserStore;967                const string errorId = "CannotCreateUserStore";968                ThrowInvalidOperation(errorId, message);969            }970 971            const SMASecurity.NativeMethods.CertOpenStoreFlags StoreFlags =972                    SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_STORE_CREATE_NEW_FLAG |973                    SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_STORE_MAXIMUM_ALLOWED_FLAG |974                    SMASecurity.NativeMethods.CertOpenStoreFlags.CERT_SYSTEM_STORE_LOCAL_MACHINE;975 976            // Create new store977            IntPtr hCertStore = SMASecurity.NativeMethods.CertOpenStore(978                                SMASecurity.NativeMethods.CertOpenStoreProvider.CERT_STORE_PROV_SYSTEM,979                                SMASecurity.NativeMethods.CertOpenStoreEncodingType.X509_ASN_ENCODING,980                                IntPtr.Zero,  // hCryptProv981                                StoreFlags,982                                pathElements[1]);983            if (hCertStore == IntPtr.Zero)984            {985                throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());986            }987            else // free native store handle988            {989                bool fResult = false;990                fResult = SMASecurity.NativeMethods.CertCloseStore(hCertStore, 0);991            }992 993            X509Store outStore = new(pathElements[1], StoreLocation.LocalMachine);994            WriteItemObject(outStore, path, true);995        }996 997        #region DriveCmdletProvider overrides998 999        /// <summary>1000        /// Initializes the cert: drive.1001        /// </summary>1002        /// <returns>1003        /// A collection that contains the PSDriveInfo object1004        /// that represents the cert: drive.1005        /// </returns>1006        protected override Collection<PSDriveInfo> InitializeDefaultDrives()1007        {1008            string providerDescription = CertificateProviderStrings.CertProvidername;1009 1010            PSDriveInfo drive = new(1011                name: "Cert",1012                provider: ProviderInfo,1013                root: @"\",1014                providerDescription,1015                credential: null);1016 1017            Collection<PSDriveInfo> drives = new();1018            drives.Add(drive);1019 1020            return drives;1021        }1022 1023        /// <summary>1024        /// Determines if the item at the given path is a store-location1025        /// or store with items in it.1026        /// </summary>1027        /// <param name="path">1028        /// The full path to the item.1029        /// </param>1030        /// <returns>1031        /// True if the path refers to a store location, or store that contains1032        /// certificates.  False otherwise.1033        /// </returns>1034        /// <exception cref="System.ArgumentNullException">1035        /// Path is null1036        /// </exception>1037        /// <exception cref="System.Security.Cryptography.CryptographicException">1038        /// This exception can be thrown if any cryptographic error occurs.1039        /// It is not possible to know exactly what went wrong.1040        /// This is because of the way CryptographicException is designed.1041        /// Some example reasons include:1042        ///  -- certificate is invalid1043        ///  -- certificate has no private key1044        ///  -- certificate password mismatch1045        /// </exception>1046        protected override bool HasChildItems(string path)1047        {1048            bool result = false;1049 1050            Utils.CheckArgForNull(path, "path");1051 1052            path = NormalizePath(path);1053 1054            if (path.Length == 0)1055            {1056                return true;1057            }1058 1059            bool isContainer = false;1060 1061            object item = GetItemAtPath(path, false, out isContainer);1062 1063            if ((item != null) && isContainer)1064            {1065                if (item is X509StoreLocation storeLocation)1066                {1067                    result = storeLocation.StoreNames.Count > 0;1068                }1069                else if (item is X509NativeStore store)1070                {1071                    store.Open(IncludeArchivedCerts());1072                    IntPtr certContext = store.GetFirstCert();1073                    if (certContext != IntPtr.Zero)1074                    {1075                        store.FreeCert(certContext);1076                        result = true;1077                    }1078                }1079            }1080 1081            return result;1082        }1083 1084        /// <summary>1085        /// Determines if the specified path is syntactically and semantically valid.1086        /// An example path looks like this:1087        ///     cert:\CurrentUser\My\5F98EBBFE735CDDAE00E33E0FD69050EF9220254.1088        /// </summary>1089        /// <param name="path">1090        /// The path of the item to check.1091        /// </param>1092        /// <returns>1093        /// True if the path is valid, false otherwise.1094        /// </returns>1095        protected override bool IsValidPath(string path)1096        {1097            path = NormalizePath(path);1098            path = EnsureDriveIsRooted(path);1099 1100            bool isCertPath = CertPathRegex.Match(path).Success;1101 1102            return isCertPath;1103        }1104 1105        /// <summary>1106        /// Determines if the store location, store, or certificate exists1107        /// at the specified path.1108        /// </summary>1109        /// <remarks>1110        /// The method ItemExists will be hit by all built-in cmdlets that interact1111        /// with the CertificateProvider except for the New-Item. They are:1112        ///     Get-ChildItem1113        ///     Set-Location1114        ///     Push-Location1115        ///     Pop-Location1116        ///     Move-Item1117        ///     Invoke-Item1118        ///     Get-Item1119        ///     Remove-Item1120        /// So we import the PKI module in this method if we haven't tried yet.1121        /// </remarks>1122        /// <param name="path">1123        /// The path of the item to check.1124        /// </param>1125        /// <returns>1126        /// True if a the store location, store, or certificate exists1127        /// at the specified path.  False otherwise.1128        /// </returns>1129        /// <exception cref="System.ArgumentNullException">1130        /// Path is null1131        /// </exception>1132        /// <exception cref="System.Security.Cryptography.CryptographicException">1133        /// This exception can be thrown if any cryptographic error occurs.1134        /// It is not possible to know exactly what went wrong.1135        /// This is because of the way CryptographicException is designed.1136        /// Possible reasons:1137        ///  -- certificate is invalid1138        ///  -- certificate has no private key1139        ///  -- certificate password mismatch1140        ///  -- etc1141        /// </exception>1142        protected override bool ItemExists(string path)1143        {1144            if (!_hasAttemptedToLoadPkiModule)1145            {1146                // Attempt to load the PKI module if we haven't tried yet1147                AttemptToImportPkiModule();1148            }1149 1150            Utils.CheckArgForNull(path, "path");1151            bool result = false;1152            bool isContainer = false;1153            object item = null;1154 1155            path = NormalizePath(path);1156 1157            if (path.Length == 0)1158            {1159                result = true;1160            }1161            else1162            {1163                //1164                // We fetch the item to see if it exists. This is1165                // because the managed cert infrastructure does not1166                // provide a way to test for existence.1167                //1168                try1169                {1170                    item = GetItemAtPath(path, true, out isContainer);1171                }1172                catch (ProviderInvocationException e)1173                {1174                    //1175                    // if the item is not found, we get ProviderInvocationException1176                    // with inner exception set to CertificateProviderItemNotFoundException1177                    // If the inner exception is not of that type1178                    // then we need to rethrow1179                    //1180                    if (e.InnerException is not CertificateProviderItemNotFoundException)1181                    {1182                        throw;1183                    }1184                }1185 1186                result = (bool)item;1187            }1188 1189            s_tracer.WriteLine("result = {0}", result);1190            return result;1191        }1192 1193        /// <summary>1194        /// Gets the store location, store, or certificate1195        /// at the specified path.1196        /// </summary>1197        /// <param name="path">1198        /// The path of the item to retrieve.1199        /// </param>1200        /// <exception cref="System.ArgumentNullException">

Showing the first 1,200 of 3566 lines. Download the file for the rest.