Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
MshSignature.cs431 linesDownload Raw Back to security
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.ComponentModel;5using System.Management.Automation.Internal;6using System.Security.Cryptography.X509Certificates;7 8using DWORD = System.UInt32;9 10namespace System.Management.Automation11{12    internal static class Win32Errors13    {14        internal const DWORD NO_ERROR = 0;15        internal const DWORD E_FAIL = 0x80004005;16        internal const DWORD TRUST_E_NOSIGNATURE = 0x800b0100;17        internal const DWORD TRUST_E_BAD_DIGEST = 0x80096010;18        internal const DWORD TRUST_E_PROVIDER_UNKNOWN = 0x800b0001;19        internal const DWORD TRUST_E_SUBJECT_FORM_UNKNOWN = 0x800B0003;20        internal const DWORD CERT_E_UNTRUSTEDROOT = 0x800b0109;21        internal const DWORD TRUST_E_EXPLICIT_DISTRUST = 0x800B0111;22        internal const DWORD CRYPT_E_BAD_MSG = 0x8009200d;23        internal const DWORD NTE_BAD_ALGID = 0x80090008;24    }25 26    /// <summary>27    /// Defines the valid status flags that a signature28    /// on a file may have.29    /// </summary>30    public enum SignatureStatus31    {32        /// <summary>33        /// The file has a valid signature.  This means only that34        /// the signature is syntactically valid.  It does not35        /// imply trust in any way.36        /// </summary>37        Valid,38 39        /// <summary>40        /// The file has an invalid signature.41        /// </summary>42        UnknownError,43 44        /// <summary>45        /// The file has no signature.46        /// </summary>47        NotSigned,48 49        /// <summary>50        /// The hash of the file does not match the hash stored51        /// along with the signature.52        /// </summary>53        HashMismatch,54 55        /// <summary>56        /// The certificate was signed by a publisher not trusted57        /// on the system.58        /// </summary>59        NotTrusted,60 61        /// <summary>62        /// The specified file format is not supported by the system63        /// for signing operations.  This usually means that the64        /// system does not know how to sign or verify the file65        /// type requested.66        /// </summary>67        NotSupportedFileFormat,68 69        /// <summary>70        /// The signature cannot be verified because it is incompatible71        /// with the current system.72        /// </summary>73        Incompatible74    }75 76    /// <summary>77    /// Defines the valid types of signatures.78    /// </summary>79    public enum SignatureType80    {81        /// <summary>82        /// The file is not signed.83        /// </summary>84        None = 0,85 86        /// <summary>87        /// The signature is an Authenticode signature embedded into the file itself.88        /// </summary>89        Authenticode = 1,90 91        /// <summary>92        /// The signature is a catalog signature.93        /// </summary>94        Catalog = 295    }96 97    /// <summary>98    /// Represents a digital signature on a signed99    /// file.100    /// </summary>101    public sealed class Signature102    {103        private string _path;104        private SignatureStatus _status = SignatureStatus.UnknownError;105        private DWORD _win32Error;106        private X509Certificate2 _signerCert;107        private string _statusMessage = string.Empty;108        private X509Certificate2 _timeStamperCert;109        // private DateTime signedOn = new DateTime(0);110 111        // Three states:112        //   - True: we can rely on the catalog API to check catalog signature.113        //   - False: we cannot rely on the catalog API, either because it doesn't exist in the OS (win7, nano),114        //            or it's not working properly (OneCore SKUs or dev environment where powershell might115        //            be updated/refreshed).116        //   - Null: it's not determined yet whether catalog API can be relied on or not.117        internal static bool? CatalogApiAvailable = null;118 119        /// <summary>120        /// Gets the X509 certificate of the publisher that121        /// signed the file.122        /// </summary>123        public X509Certificate2 SignerCertificate124        {125            get126            {127                return _signerCert;128            }129        }130 131        /// <summary>132        /// Gets the X509 certificate of the authority that133        /// time-stamped the file.134        /// </summary>135        public X509Certificate2 TimeStamperCertificate136        {137            get138            {139                return _timeStamperCert;140            }141        }142 143        /// <summary>144        /// Gets the status of the signature on the file.145        /// </summary>146        public SignatureStatus Status147        {148            get149            {150                return _status;151            }152        }153 154        /// <summary>155        /// Gets the message corresponding to the status of the156        /// signature on the file.157        /// </summary>158        public string StatusMessage159        {160            get161            {162                return _statusMessage;163            }164        }165 166        /// <summary>167        /// Gets the path of the file to which this signature168        /// applies.169        /// </summary>170        public string Path171        {172            get173            {174                return _path;175            }176        }177 178        /// <summary>179        /// Returns the signature type of the signature.180        /// </summary>181        public SignatureType SignatureType { get; internal set; }182 183        /// <summary>184        /// True if the item is signed as part of an operating system release.185        /// </summary>186        public bool IsOSBinary { get; internal set; }187 188        /// <summary>189        /// Gets the Subject Alternative Name from the signer certificate.190        /// </summary>191        public string[] SubjectAlternativeName { get; private set; }192 193        /// <summary>194        /// Constructor for class Signature195        ///196        /// Call this to create a validated time-stamped signature object.197        /// </summary>198        /// <param name="filePath">This signature is found in this file.</param>199        /// <param name="error">Win32 error code.</param>200        /// <param name="signer">Cert of the signer.</param>201        /// <param name="timestamper">Cert of the time stamper.</param>202        /// <returns>Constructed object.</returns>203        internal Signature(string filePath,204                           DWORD error,205                           X509Certificate2 signer,206                           X509Certificate2 timestamper)207        {208            Utils.CheckArgForNullOrEmpty(filePath, "filePath");209            Utils.CheckArgForNull(signer, "signer");210            Utils.CheckArgForNull(timestamper, "timestamper");211 212            Init(filePath, signer, error, timestamper);213        }214 215        /// <summary>216        /// Constructor for class Signature217        ///218        /// Call this to create a validated signature object.219        /// </summary>220        /// <param name="filePath">This signature is found in this file.</param>221        /// <param name="signer">Cert of the signer.</param>222        /// <returns>Constructed object.</returns>223        internal Signature(string filePath,224                           X509Certificate2 signer)225        {226            Utils.CheckArgForNullOrEmpty(filePath, "filePath");227            Utils.CheckArgForNull(signer, "signer");228 229            Init(filePath, signer, 0, null);230        }231 232        /// <summary>233        /// Constructor for class Signature234        ///235        /// Call this ctor when creating an invalid signature object.236        /// </summary>237        /// <param name="filePath">This signature is found in this file.</param>238        /// <param name="error">Win32 error code.</param>239        /// <param name="signer">Cert of the signer.</param>240        /// <returns>Constructed object.</returns>241        internal Signature(string filePath,242                           DWORD error,243                           X509Certificate2 signer)244        {245            Utils.CheckArgForNullOrEmpty(filePath, "filePath");246            Utils.CheckArgForNull(signer, "signer");247 248            Init(filePath, signer, error, null);249        }250 251        /// <summary>252        /// Constructor for class Signature253        ///254        /// Call this ctor when creating an invalid signature object.255        /// </summary>256        /// <param name="filePath">This signature is found in this file.</param>257        /// <param name="error">Win32 error code.</param>258        /// <returns>Constructed object.</returns>259        internal Signature(string filePath, DWORD error)260        {261            Utils.CheckArgForNullOrEmpty(filePath, "filePath");262 263            Init(filePath, null, error, null);264        }265 266        private void Init(string filePath,267                          X509Certificate2 signer,268                          DWORD error,269                          X509Certificate2 timestamper)270        {271            _path = filePath;272            _win32Error = error;273            _signerCert = signer;274            _timeStamperCert = timestamper;275            SignatureType = SignatureType.None;276 277            SignatureStatus isc =278                GetSignatureStatusFromWin32Error(error);279 280            _status = isc;281 282            _statusMessage = GetSignatureStatusMessage(isc,283                                                      error,284                                                      filePath);285 286            // Extract Subject Alternative Name from the signer certificate287            SubjectAlternativeName = GetSubjectAlternativeName(signer);288        }289 290        private static SignatureStatus GetSignatureStatusFromWin32Error(DWORD error)291        {292            SignatureStatus isc = SignatureStatus.UnknownError;293 294            switch (error)295            {296                case Win32Errors.NO_ERROR:297                    isc = SignatureStatus.Valid;298                    break;299 300                case Win32Errors.NTE_BAD_ALGID:301                    isc = SignatureStatus.Incompatible;302                    break;303 304                case Win32Errors.TRUST_E_NOSIGNATURE:305                    isc = SignatureStatus.NotSigned;306                    break;307 308                case Win32Errors.TRUST_E_BAD_DIGEST:309                case Win32Errors.CRYPT_E_BAD_MSG:310                    isc = SignatureStatus.HashMismatch;311                    break;312 313                case Win32Errors.TRUST_E_PROVIDER_UNKNOWN:314                    isc = SignatureStatus.NotSupportedFileFormat;315                    break;316 317                case Win32Errors.TRUST_E_EXPLICIT_DISTRUST:318                    isc = SignatureStatus.NotTrusted;319                    break;320            }321 322            return isc;323        }324 325        private static string GetSignatureStatusMessage(SignatureStatus status,326                                                 DWORD error,327                                                 string filePath)328        {329            string message = null;330            string resourceString = null;331            string arg = null;332 333            switch (status)334            {335                case SignatureStatus.Valid:336                    resourceString = MshSignature.MshSignature_Valid;337                    break;338 339                case SignatureStatus.UnknownError:340                    int intError = SecuritySupport.GetIntFromDWORD(error);341                    Win32Exception e = new Win32Exception(intError);342                    message = e.Message;343                    break;344 345                case SignatureStatus.Incompatible:346                    if (error == Win32Errors.NTE_BAD_ALGID)347                    {348                        resourceString = MshSignature.MshSignature_Incompatible_HashAlgorithm;349                    }350                    else351                    {352                        resourceString = MshSignature.MshSignature_Incompatible;353                    }354 355                    arg = filePath;356                    break;357 358                case SignatureStatus.NotSigned:359                    resourceString = MshSignature.MshSignature_NotSigned;360                    arg = filePath;361                    break;362 363                case SignatureStatus.HashMismatch:364                    resourceString = MshSignature.MshSignature_HashMismatch;365                    arg = filePath;366                    break;367 368                case SignatureStatus.NotTrusted:369                    resourceString = MshSignature.MshSignature_NotTrusted;370                    arg = filePath;371                    break;372 373                case SignatureStatus.NotSupportedFileFormat:374                    resourceString = MshSignature.MshSignature_NotSupportedFileFormat;375                    arg = System.IO.Path.GetExtension(filePath);376 377                    if (string.IsNullOrEmpty(arg))378                    {379                        resourceString = MshSignature.MshSignature_NotSupportedFileFormat_NoExtension;380                        arg = null;381                    }382 383                    break;384            }385 386            if (message == null)387            {388                if (arg == null)389                {390                    message = resourceString;391                }392                else393                {394                    message = StringUtil.Format(resourceString, arg);395                }396            }397 398            return message;399        }400 401        /// <summary>402        /// Extracts the Subject Alternative Name from the certificate.403        /// </summary>404        /// <param name="certificate">The certificate to extract SAN from.</param>405        /// <returns>Array of SAN entries or null if not found.</returns>406        private static string[] GetSubjectAlternativeName(X509Certificate2 certificate)407        {408            if (certificate == null)409            {410                return null;411            }412 413            foreach (X509Extension extension in certificate.Extensions)414            {415                if (extension.Oid != null && extension.Oid.Value == CertificateFilterInfo.SubjectAlternativeNameOid)416                {417                    string formatted = extension.Format(multiLine: true);418                    if (string.IsNullOrEmpty(formatted))419                    {420                        return null;421                    }422 423                    return formatted.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);424                }425            }426 427            return null;428        }429    }430}431