Example #1
0
        private static BigIntegerRSAPublicKey ThaliServerCertificateValidationCallback(
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
        {
            if (certificate == null || (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != 0)
            {
                throw new ApplicationException();
            }

            if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0)
            {
                const X509ChainStatusFlags AcceptableCertChainErrors = X509ChainStatusFlags.UntrustedRoot
                                                                       | X509ChainStatusFlags.RevocationStatusUnknown
                                                                       | X509ChainStatusFlags.OfflineRevocation
                                                                       | X509ChainStatusFlags.NoError;
                if (
                    chain.ChainStatus.Any(
                        chainStatus => (chainStatus.Status | AcceptableCertChainErrors) != AcceptableCertChainErrors))
                {
                    throw new ApplicationException();
                }
            }

            // TODO: Actually prove that the last entry in the chain is the root
            var x509Certv2 = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
            var serverPublicKeyParameters =
                ((RSACryptoServiceProvider)x509Certv2.PublicKey.Key).ExportParameters(false);
            var serverPresentedRsaKey = new BigIntegerRSAPublicKey(serverPublicKeyParameters);

            return(serverPresentedRsaKey);
        }
Example #2
0
        // private stuff

        // note: flags isn't a flag (i.e. multiple values) when used here
        static internal string GetInformation(X509ChainStatusFlags flags)
        {
            switch (flags)
            {
            case X509ChainStatusFlags.NotTimeValid:
            case X509ChainStatusFlags.NotTimeNested:
            case X509ChainStatusFlags.Revoked:
            case X509ChainStatusFlags.NotSignatureValid:
            case X509ChainStatusFlags.NotValidForUsage:
            case X509ChainStatusFlags.UntrustedRoot:
            case X509ChainStatusFlags.RevocationStatusUnknown:
            case X509ChainStatusFlags.Cyclic:
            case X509ChainStatusFlags.InvalidExtension:
            case X509ChainStatusFlags.InvalidPolicyConstraints:
            case X509ChainStatusFlags.InvalidBasicConstraints:
            case X509ChainStatusFlags.InvalidNameConstraints:
            case X509ChainStatusFlags.HasNotSupportedNameConstraint:
            case X509ChainStatusFlags.HasNotDefinedNameConstraint:
            case X509ChainStatusFlags.HasNotPermittedNameConstraint:
            case X509ChainStatusFlags.HasExcludedNameConstraint:
            case X509ChainStatusFlags.PartialChain:
            case X509ChainStatusFlags.CtlNotTimeValid:
            case X509ChainStatusFlags.CtlNotSignatureValid:
            case X509ChainStatusFlags.CtlNotValidForUsage:
            case X509ChainStatusFlags.OfflineRevocation:
            case X509ChainStatusFlags.NoIssuanceChainPolicy:
                return(Locale.GetText(flags.ToString()));                  // FIXME - add a better description

            case X509ChainStatusFlags.NoError:
            default:
                // should never happen
                return(String.Empty);
            }
        }
Example #3
0
        protected override int InternalExecute()
        {
            if (string.IsNullOrEmpty(this.certRawData))
            {
                return(-1);
            }
            int result;

            try
            {
                byte[]           rawData     = Convert.FromBase64String(this.certRawData);
                X509Certificate2 certificate = new X509Certificate2(rawData);
                X509Chain        x509Chain   = new X509Chain(true);
                x509Chain.Build(certificate);
                X509ChainStatusFlags x509ChainStatusFlags = X509ChainStatusFlags.NoError;
                foreach (X509ChainStatus x509ChainStatus in x509Chain.ChainStatus)
                {
                    x509ChainStatusFlags |= x509ChainStatus.Status;
                }
                result = (int)x509ChainStatusFlags;
            }
            catch
            {
                result = -1;
            }
            return(result);
        }
Example #4
0
 private bool IsParent(X509Certificate child, X509Certificate parent)
 {
     if (child.IssuerName != parent.SubjectName)
     {
         return(false);
     }
     if (parent.Version > 2 && !this.IsTrusted(parent))
     {
         X509Extension x509Extension = parent.Extensions["2.5.29.19"];
         if (x509Extension != null)
         {
             BasicConstraintsExtension basicConstraintsExtension = new BasicConstraintsExtension(x509Extension);
             if (!basicConstraintsExtension.CertificateAuthority)
             {
                 this._status = X509ChainStatusFlags.InvalidBasicConstraints;
             }
         }
         else
         {
             this._status = X509ChainStatusFlags.InvalidBasicConstraints;
         }
     }
     if (!child.VerifySignature(parent.RSA))
     {
         this._status = X509ChainStatusFlags.NotSignatureValid;
         return(false);
     }
     return(true);
 }
Example #5
0
 public X509ChainErrorMapping(CertTrustErrorStatus win32Flag, int win32ErrorCode, X509ChainStatusFlags chainStatusFlag)
 {
     Win32Flag       = win32Flag;
     Win32ErrorCode  = win32ErrorCode;
     ChainStatusFlag = chainStatusFlag;
     Message         = Interop.Kernel32.GetMessage(win32ErrorCode);
 }
Example #6
0
        private static void FixupStatus(
            X509Certificate2 cert,
            X509RevocationMode revocationMode,
            ref int dwStatus)
        {
            X509ChainStatusFlags flags = (X509ChainStatusFlags)dwStatus;

            if ((flags & X509ChainStatusFlags.UntrustedRoot) != 0)
            {
                X509ChainStatusFlags newFlag = FindUntrustedRootReason(cert);

                if (newFlag != X509ChainStatusFlags.UntrustedRoot)
                {
                    flags &= ~X509ChainStatusFlags.UntrustedRoot;
                    flags |= newFlag;

                    dwStatus = (int)flags;
                }
            }

            if (revocationMode == X509RevocationMode.NoCheck)
            {
                // Clear any revocation-related flags if NoCheck was requested, since
                // the OS may use cached results opportunistically.
                flags &= ~RevocationRelevantFlags;

                dwStatus = (int)flags;
            }
        }
Example #7
0
 private X509Certificate FindCertificateRoot(X509Certificate potentialRoot)
 {
     if (potentialRoot == null)
     {
         this._status = X509ChainStatusFlags.PartialChain;
         return(null);
     }
     if (this.IsTrusted(potentialRoot))
     {
         return(potentialRoot);
     }
     foreach (X509Certificate x509Certificate in this.TrustAnchors)
     {
         if (this.IsParent(potentialRoot, x509Certificate))
         {
             return(x509Certificate);
         }
     }
     if (potentialRoot.IsSelfSigned)
     {
         this._status = X509ChainStatusFlags.UntrustedRoot;
         return(potentialRoot);
     }
     this._status = X509ChainStatusFlags.PartialChain;
     return(null);
 }
        private static void AddElementStatus(
            Interop.Crypto.X509VerifyStatusCode errorCode,
            List <X509ChainStatus> elementStatus,
            List <X509ChainStatus> overallStatus)
        {
            X509ChainStatusFlags statusFlag = MapVerifyErrorToChainStatus(errorCode);

            Debug.Assert(
                (statusFlag & (statusFlag - 1)) == 0,
                "Status flag has more than one bit set",
                "More than one bit is set in status '{0}' for error code '{1}'",
                statusFlag,
                errorCode);

            foreach (X509ChainStatus currentStatus in elementStatus)
            {
                if ((currentStatus.Status & statusFlag) != 0)
                {
                    return;
                }
            }

            X509ChainStatus chainStatus = new X509ChainStatus
            {
                Status            = statusFlag,
                StatusInformation = Interop.Crypto.GetX509VerifyCertErrorString(errorCode),
            };

            elementStatus.Add(chainStatus);
            AddUniqueStatus(overallStatus, ref chainStatus);
        }
Example #9
0
        /// <summary>
        /// Create a Trust Model from the given settings
        /// </summary>
        /// <returns>TrustModel</returns>
        public TrustModel CreateTrustModel()
        {
            TrustChainValidator validator = new TrustChainValidator();

            validator.RevocationCheckMode        = this.RevocationCheckMode;
            validator.RevocationCheckGranularity = this.RevocationCheckGranularity;
            if (this.MaxIssuerChainLength > 0)
            {
                validator.MaxIssuerChainLength = this.MaxIssuerChainLength;
            }
            if (this.TimeoutMilliseconds > 0)
            {
                validator.ValidationPolicy.UrlRetrievalTimeout = TimeSpan.FromMilliseconds(this.TimeoutMilliseconds);
            }

            TrustModel trustModel = new TrustModel(validator);

            if (this.ProblemFlags != null)
            {
                X509ChainStatusFlags flags = X509ChainStatusFlags.NoError;
                foreach (X509ChainStatusFlags flag in this.ProblemFlags)
                {
                    flags = (flags | flag);
                }
                trustModel.CertChainValidator.ProblemFlags = flags;
            }

            return(trustModel);
        }
Example #10
0
        public static void EmptyAiaResponseIsIgnored()
        {
            CertificateAuthority.BuildPrivatePki(
                PkiOptions.AllRevocation,
                out RevocationResponder responder,
                out CertificateAuthority root,
                out CertificateAuthority intermediate,
                out X509Certificate2 endEntity,
                pkiOptionsInSubject: false);

            using (responder)
                using (root)
                    using (intermediate)
                        using (endEntity)
                            using (ChainHolder holder = new ChainHolder())
                                using (X509Certificate2 rootCert = root.CloneIssuerCert())
                                    using (X509Certificate2 intermediateCert = intermediate.CloneIssuerCert())
                                    {
                                        responder.RespondEmpty = true;

                                        X509Chain chain = holder.Chain;
                                        chain.ChainPolicy.TrustMode           = X509ChainTrustMode.CustomRootTrust;
                                        chain.ChainPolicy.VerificationTime    = endEntity.NotBefore.AddMinutes(1);
                                        chain.ChainPolicy.UrlRetrievalTimeout = DynamicRevocationTests.s_urlRetrievalLimit;
                                        chain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;

                                        Assert.False(chain.Build(endEntity));
                                        X509ChainStatusFlags chainFlags = chain.AllStatusFlags();
                                        Assert.True(chainFlags.HasFlag(X509ChainStatusFlags.PartialChain), $"expected partial chain flags, got {chainFlags}");
                                    }
        }
Example #11
0
        public static void CustomRootTrustDoesNotTrustIntermediates(
            bool saveAllInCustomTrustStore,
            X509ChainStatusFlags chainFlags)
        {
            TestDataGenerator.MakeTestChain3(
                out X509Certificate2 endEntityCert,
                out X509Certificate2 intermediateCert,
                out X509Certificate2 rootCert);

            using (endEntityCert)
                using (intermediateCert)
                    using (rootCert)
                        using (ChainHolder chainHolder = new ChainHolder())
                        {
                            X509Chain chain = chainHolder.Chain;
                            chain.ChainPolicy.RevocationMode   = X509RevocationMode.NoCheck;
                            chain.ChainPolicy.VerificationTime = endEntityCert.NotBefore.AddSeconds(1);
                            chain.ChainPolicy.TrustMode        = X509ChainTrustMode.CustomRootTrust;
                            chain.ChainPolicy.CustomTrustStore.Add(intermediateCert);

                            if (saveAllInCustomTrustStore)
                            {
                                chain.ChainPolicy.CustomTrustStore.Add(rootCert);
                            }
                            else
                            {
                                chain.ChainPolicy.ExtraStore.Add(rootCert);
                            }

                            Assert.Equal(saveAllInCustomTrustStore, chain.Build(endEntityCert));
                            Assert.Equal(3, chain.ChainElements.Count);
                            Assert.Equal(chainFlags, chain.AllStatusFlags());
                        }
        }
Example #12
0
        private bool IsParent(X509Certificate child, X509Certificate parent)
        {
            if (child.IssuerName != parent.SubjectName)
            {
                return(false);
            }

            // parent MUST have the Basic Constraint CA=true (except for trusted roots)
            // see why at http://www.microsoft.com/technet/security/bulletin/MS02-050.asp
            if ((parent.Version > 2) && (!IsTrusted(parent)))
            {
                // TODO: we do not support pathLenConstraint
                X509Extension ext = parent.Extensions ["2.5.29.19"];
                if (ext != null)
                {
                    BasicConstraintsExtension bc = new BasicConstraintsExtension(ext);
                    if (!bc.CertificateAuthority)
                    {
                        _status = X509ChainStatusFlags.InvalidBasicConstraints;
                    }
                }
                else
                {
                    _status = X509ChainStatusFlags.InvalidBasicConstraints;
                }
            }

            if (!child.VerifySignature(parent.RSA))
            {
                _status = X509ChainStatusFlags.NotSignatureValid;
                return(false);
            }
            return(true);
        }
Example #13
0
        private X509Certificate FindCertificateRoot(X509Certificate potentialRoot)
        {
            if (potentialRoot == null)
            {
                _status = X509ChainStatusFlags.PartialChain;
                return(null);
            }

            // if the trusted root is in the chain
            if (IsTrusted(potentialRoot))
            {
                return(potentialRoot);
            }

            // if the root isn't in the chain
            foreach (X509Certificate root in TrustAnchors)
            {
                if (IsParent(potentialRoot, root))
                {
                    return(root);
                }
            }

            // is it a (untrusted) root ?
            if (potentialRoot.IsSelfSigned)
            {
                _status = X509ChainStatusFlags.UntrustedRoot;
                return(potentialRoot);
            }

            _status = X509ChainStatusFlags.PartialChain;
            return(null);
        }
		// private stuff

		// note: flags isn't a flag (i.e. multiple values) when used here
		static internal string GetInformation (X509ChainStatusFlags flags)
		{
			switch (flags) {
			case X509ChainStatusFlags.NotTimeValid:
			case X509ChainStatusFlags.NotTimeNested:
			case X509ChainStatusFlags.Revoked:
			case X509ChainStatusFlags.NotSignatureValid:
			case X509ChainStatusFlags.NotValidForUsage:
			case X509ChainStatusFlags.UntrustedRoot:
			case X509ChainStatusFlags.RevocationStatusUnknown:
			case X509ChainStatusFlags.Cyclic:
			case X509ChainStatusFlags.InvalidExtension:
			case X509ChainStatusFlags.InvalidPolicyConstraints:
			case X509ChainStatusFlags.InvalidBasicConstraints:
			case X509ChainStatusFlags.InvalidNameConstraints:
			case X509ChainStatusFlags.HasNotSupportedNameConstraint:
			case X509ChainStatusFlags.HasNotDefinedNameConstraint:
			case X509ChainStatusFlags.HasNotPermittedNameConstraint:
			case X509ChainStatusFlags.HasExcludedNameConstraint:
			case X509ChainStatusFlags.PartialChain:
			case X509ChainStatusFlags.CtlNotTimeValid:
			case X509ChainStatusFlags.CtlNotSignatureValid:
			case X509ChainStatusFlags.CtlNotValidForUsage:
			case X509ChainStatusFlags.OfflineRevocation:
			case X509ChainStatusFlags.NoIssuanceChainPolicy:
				return Locale.GetText (flags.ToString ()); // FIXME - add a better description
			case X509ChainStatusFlags.NoError:
			default:
				// should never happen
				return String.Empty;
			}
		}
        private static string RunChain(
            X509Chain chain,
            X509Certificate2 cert,
            string msg)
        {
            bool success = chain.Build(cert);

            FormattableString errMsg = null;

            if (!success)
            {
                for (int i = 0; i < chain.ChainElements.Count; i++)
                {
                    X509ChainElement element = chain.ChainElements[i];

                    if (element.ChainElementStatus.Length != 0)
                    {
                        X509ChainStatusFlags flags =
                            element.ChainElementStatus.Select(ces => ces.Status).Aggregate((a, b) => a | b);

                        errMsg = $"{msg}: chain error at depth {i}: {flags}";
                        break;
                    }
                }
            }

            return(errMsg?.ToString(formatProvider: CultureInfo.CurrentCulture));
        }
            public void InvalidCertificateInvalidatesSignatures(
                EndCertificateUse use,
                X509ChainStatusFlags flags,
                SignatureDecision ingestionDecision,
                SignatureDecision gracePeriodDecision,
                SignatureDecision afterGracePeriodDecision)
            {
                // Arrange
                var certificate = new EndCertificate {
                    Use = use
                };

                var result = new CertificateVerificationResult(
                    status: EndCertificateStatus.Invalid,
                    statusFlags: flags);

                var signatureAtIngestion = new PackageSignature {
                    Status = PackageSignatureStatus.Unknown
                };
                var signatureAtGracePeriod = new PackageSignature {
                    Status = PackageSignatureStatus.InGracePeriod
                };
                var signatureAfterGracePeriod = new PackageSignature {
                    Status = PackageSignatureStatus.Valid
                };

                // Act & Assert
                var decider = _target.MakeDeciderForInvalidatedCertificate(certificate, result);

                Assert.Equal(ingestionDecision, decider(signatureAtIngestion));
                Assert.Equal(gracePeriodDecision, decider(signatureAtGracePeriod));
                Assert.Equal(afterGracePeriodDecision, decider(signatureAfterGracePeriod));
            }
        // Performs Attestation per the protocol used by Virtual Secure Modules.
        private void VerifyAttestationInfo(string attestationUrl, HealthReport healthReport, EnclaveReportPackage enclaveReportPackage)
        {
            bool shouldRetryValidation;
            bool shouldForceUpdateSigningKeys = false;

            do
            {
                shouldRetryValidation = false;

                // Get HGS Root signing certs from HGS
                X509Certificate2Collection signingCerts = GetSigningCertificate(attestationUrl, shouldForceUpdateSigningKeys);

                // Verify SQL Health report root chain of trust is the HGS root signing cert
                X509ChainStatusFlags chainStatus = VerifyHealthReportAgainstRootCertificate(signingCerts, healthReport.Certificate);
                if (chainStatus != X509ChainStatusFlags.NoError)
                {
                    // In cases if we fail to validate the health report, it might be possible that we are using old signing keys
                    // let's re-download the signing keys again and re-validate the health report
                    if (!shouldForceUpdateSigningKeys)
                    {
                        shouldForceUpdateSigningKeys = true;
                        shouldRetryValidation        = true;
                    }
                    else
                    {
                        throw new AlwaysEncryptedAttestationException(String.Format(Strings.VerifyHealthCertificateChainFormat, attestationUrl, chainStatus));
                    }
                }
            } while (shouldRetryValidation);

            // Verify enclave report is signed by IDK_S from health report
            VerifyEnclaveReportSignature(enclaveReportPackage, healthReport.Certificate);
        }
Example #18
0
 private X509Certificate FindCertificateRoot(X509Certificate potentialRoot)
 {
     if (potentialRoot == null)
     {
         _status = X509ChainStatusFlags.PartialChain;
         return(null);
     }
     if (IsTrusted(potentialRoot))
     {
         return(potentialRoot);
     }
     foreach (X509Certificate trustAnchor in TrustAnchors)
     {
         if (IsParent(potentialRoot, trustAnchor))
         {
             return(trustAnchor);
         }
     }
     if (potentialRoot.IsSelfSigned)
     {
         _status = X509ChainStatusFlags.UntrustedRoot;
         return(potentialRoot);
     }
     _status = X509ChainStatusFlags.PartialChain;
     return(null);
 }
Example #19
0
        public static void TestLeafCertificateWithUnknownCriticalExtension()
        {
            using (RSA key = RSA.Create())
            {
                CertificateRequest certReq = new CertificateRequest(
                    new X500DistinguishedName("CN=Cert"),
                    key,
                    HashAlgorithmName.SHA256,
                    RSASignaturePadding.Pkcs1);

                const string PrecertificatePoisonExtensionOid = "1.3.6.1.4.1.11129.2.4.3";
                certReq.CertificateExtensions.Add(new X509Extension(
                                                      new AsnEncodedData(
                                                          new Oid(PrecertificatePoisonExtensionOid),
                                                          new byte[] { 5, 0 }),
                                                      critical: true));

                DateTimeOffset notBefore = DateTimeOffset.UtcNow.AddDays(-1);
                DateTimeOffset notAfter  = notBefore.AddDays(30);

                using (X509Certificate2 cert = certReq.CreateSelfSigned(notBefore, notAfter))
                    using (ChainHolder holder = new ChainHolder())
                    {
                        X509Chain chain = holder.Chain;
                        chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                        Assert.False(chain.Build(cert));

                        X509ChainElement           certElement  = chain.ChainElements.OfType <X509ChainElement>().Single();
                        const X509ChainStatusFlags ExpectedFlag = X509ChainStatusFlags.HasNotSupportedCriticalExtension;
                        X509ChainStatusFlags       actualFlags  = certElement.AllStatusFlags();
                        Assert.True((actualFlags & ExpectedFlag) == ExpectedFlag, $"Has expected flag {ExpectedFlag} but was {actualFlags}");
                    }
            }
        }
Example #20
0
        // This isn't how RFC3280 (section 6.3) deals with CRL, but then we don't (yet) support DP, deltas...
        private X509ChainStatusFlags CheckRevocation(X509Certificate2 certificate, int ca, bool online)
        {
            X509ChainStatusFlags result  = X509ChainStatusFlags.RevocationStatusUnknown;
            X509ChainElement     element = elements [ca];
            X509Certificate2     ca_cert = element.Certificate;

            // find the CRL from the "right" CA
            while (IsSelfIssued(ca_cert) && (ca < elements.Count - 1))
            {
                // try with this self-issued
                result = CheckRevocation(certificate, ca_cert, online);
                if (result != X509ChainStatusFlags.RevocationStatusUnknown)
                {
                    break;
                }
                ca++;
                element = elements [ca];
                ca_cert = element.Certificate;
            }
            if (result == X509ChainStatusFlags.RevocationStatusUnknown)
            {
                result = CheckRevocation(certificate, ca_cert, online);
            }
            return(result);
        }
Example #21
0
        private void ValidateChain(X509ChainStatusFlags flag)
        {
            int num = this.elements.Count - 1;
            X509Certificate2 certificate = this.elements[num].Certificate;

            if ((flag & X509ChainStatusFlags.PartialChain) == X509ChainStatusFlags.NoError)
            {
                this.Process(num);
                if (num == 0)
                {
                    this.elements[0].UncompressFlags();
                    return;
                }
                num--;
            }
            this.working_public_key  = certificate.PublicKey.Key;
            this.working_issuer_name = certificate.IssuerName;
            this.max_path_length     = num;
            for (int i = num; i > 0; i--)
            {
                this.Process(i);
                this.PrepareForNextCertificate(i);
            }
            this.Process(0);
            this.CheckRevocationOnChain(flag);
            this.WrapUp();
        }
Example #22
0
        /// <summary>
        /// Create an LDAP certificate resolver, using timeout and default DNS server for SRV lookup
        /// </summary>
        /// <param name="dnsServerIp">An <see cref="IPAddress"/> IP address of the DNS server to use for DNS lookups</param>
        /// <param name="timeout">Timeout value for DNS and LDAP lookups</param>
        /// <param name="cacheEnabled">boolean flag indicating whether or not to use the DNS client with cache</param>
        public LdapCertResolver(IPAddress dnsServerIp, TimeSpan timeout, bool cacheEnabled)
        {
            if (dnsServerIp == null)
            {
                dnsServerIp = GetLocalServerDns(dnsServerIp);
            }
            if (dnsServerIp == null)
            {
                throw new ArgumentNullException("dnsServerIp");
            }

            if (timeout.Ticks < 0)
            {
                throw new ArgumentException("timeout value was less than zero", "timeout");
            }

            m_dnsServerIp  = dnsServerIp;
            m_timeout      = timeout;
            m_cacheEnabled = cacheEnabled;

            m_policy = new X509ChainPolicy();
            m_policy.VerificationFlags = (X509VerificationFlags.IgnoreWrongUsage);

            m_problemFlags = DefaultProblemFlags;
        }
        // *** certificate chain/path validation stuff ***

        // Currently a subset of RFC3280 (hopefully a full implementation someday)
        private void ValidateChain(X509ChainStatusFlags flag)
        {
            // 'n' should be the root certificate...
            int n = elements.Count - 1;
            X509Certificate2 certificate = elements [n].Certificate;

            // ... and, if so, must be treated outside the chain...
            if (((flag & X509ChainStatusFlags.PartialChain) == 0))
            {
                Process(n);
                // deal with the case where the chain == the root certificate
                // (which isn't for RFC3280) part of the chain
                if (n == 0)
                {
                    elements [0].UncompressFlags();
                    return;
                }
                // skip the root certificate when processing the chain (in 6.1.3)
                n--;
            }
            // ... unless the chain is a partial one (then we start with that one)

            // 6.1.1 - Inputs
            // 6.1.1.a - a prospective certificate path of length n (i.e. elements)
            // 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
            // 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
            // 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
            // 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
            // 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
            // 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)

            // 6.1.2 - Initialization (incomplete)
            // 6.1.2.a-f - policy stuff, some TODO, some not supported
            // 6.1.2.g - working public key algorithm
//			working_public_key_algorithm = certificate.PublicKey.Oid.Value;
            // 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
            working_public_key = certificate.PublicKey.Key;
            // 6.1.2.j - working issuer name
            working_issuer_name = certificate.IssuerName;
            // 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
            //	     may be reduced to the value in the path length constraint field
            max_path_length = n;

            // 6.1.3 - Basic Certificate Processing
            // note: loop looks reversed (the list is) but we process this part just like RFC3280 does
            for (int i = n; i > 0; i--)
            {
                Process(i);
                // 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
                PrepareForNextCertificate(i);
            }
            Process(0);

            // 6.1.3.a.3 - revocation checks
            CheckRevocationOnChain(flag);

            // 6.1.5 - Wrap-up procedure
            WrapUp();
        }
Example #24
0
 public override void AddStatus(X509ChainStatusFlags errorCode)
 {
     if (chainStatusList == null)
     {
         chainStatusList = new List <X509ChainStatus>();
     }
     chainStatusList.Add(new X509ChainStatus(errorCode));
 }
        public static void VerifyCrlCache()
        {
            string crlDirectory = PersistedFiles.GetUserFeatureDirectory("cryptography", "crls");
            string crlFile      = Path.Combine(crlDirectory, MicrosoftDotComRootCrlFilename);

            Directory.CreateDirectory(crlDirectory);
            File.Delete(crlFile);

            using (var microsoftDotComIssuer = new X509Certificate2(TestData.MicrosoftDotComIssuerBytes))
                using (var microsoftDotComRoot = new X509Certificate2(TestData.MicrosoftDotComRootBytes))
                    using (var unrelated = new X509Certificate2(TestData.DssCer))
                        using (var chainHolder = new ChainHolder())
                        {
                            X509Chain chain = chainHolder.Chain;

                            chain.ChainPolicy.ExtraStore.Add(unrelated);
                            chain.ChainPolicy.ExtraStore.Add(microsoftDotComRoot);

                            // The very start of the CRL period.
                            chain.ChainPolicy.VerificationTime   = new DateTime(2015, 6, 17, 0, 0, 0, DateTimeKind.Utc);
                            chain.ChainPolicy.RevocationMode     = X509RevocationMode.NoCheck;
                            chain.ChainPolicy.RevocationFlag     = X509RevocationFlag.EndCertificateOnly;
                            chain.ChainPolicy.VerificationFlags |= X509VerificationFlags.AllowUnknownCertificateAuthority;

                            bool valid = chain.Build(microsoftDotComIssuer);
                            Assert.True(valid, "Precondition: Chain builds with no revocation checks");

                            int initialErrorCount = chain.ChainStatus.Length;
                            Assert.InRange(initialErrorCount, 0, 1);

                            X509ChainStatusFlags initialFlags = chain.AllStatusFlags();

                            if (initialFlags != X509ChainStatusFlags.NoError)
                            {
                                Assert.Equal(X509ChainStatusFlags.UntrustedRoot, initialFlags);
                            }

                            chainHolder.DisposeChainElements();

                            chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline;

                            valid = chain.Build(microsoftDotComIssuer);
                            Assert.False(valid, "Chain should not build validly");

                            const X509ChainStatusFlags UnknownOffline =
                                X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation;

                            Assert.Equal(initialFlags | UnknownOffline, chain.AllStatusFlags());

                            File.WriteAllText(crlFile, MicrosoftDotComRootCrlPem, Encoding.ASCII);

                            chainHolder.DisposeChainElements();

                            valid = chain.Build(microsoftDotComIssuer);
                            Assert.True(valid, "Chain should build validly now");
                            Assert.Equal(initialErrorCount, chain.ChainStatus.Length);
                        }
        }
Example #26
0
        public static void InvalidSelfSignedSignature()
        {
            X509ChainStatusFlags expectedFlags;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                expectedFlags = X509ChainStatusFlags.NotSignatureValid;
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                // For OSX alone expectedFlags here means OR instead of AND.
                // Because the error code changed in 10.13.4 from UntrustedRoot to PartialChain
                // and we handle that later in this test.
                expectedFlags =
                    X509ChainStatusFlags.UntrustedRoot |
                    X509ChainStatusFlags.PartialChain;
            }
            else
            {
                expectedFlags =
                    X509ChainStatusFlags.NotSignatureValid |
                    X509ChainStatusFlags.UntrustedRoot;
            }

            byte[] certBytes = (byte[])TestData.MicrosoftDotComRootBytes.Clone();
            // The signature goes up to the very last byte, so flip some bits in it.
            certBytes[certBytes.Length - 1] ^= 0xFF;

            using (var cert = new X509Certificate2(certBytes))
                using (ChainHolder holder = new ChainHolder())
                {
                    X509Chain       chain  = holder.Chain;
                    X509ChainPolicy policy = chain.ChainPolicy;
                    policy.VerificationTime = cert.NotBefore.AddDays(3);
                    policy.RevocationMode   = X509RevocationMode.NoCheck;

                    chain.Build(cert);

                    X509ChainStatusFlags allFlags =
                        chain.ChainStatus.Select(cs => cs.Status).Aggregate(
                            X509ChainStatusFlags.NoError,
                            (a, b) => a | b);

                    if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                    {
                        // If we're on 10.13.3 or older we get UntrustedRoot.
                        // If we're on 10.13.4 or newer we get PartialChain.
                        //
                        // So make the expectedValue be whichever of those two is set.
                        expectedFlags = (expectedFlags & allFlags);
                        // One of them has to be set.
                        Assert.NotEqual(X509ChainStatusFlags.NoError, expectedFlags);
                        // Continue executing now to ensure that no other unexpected flags were set.
                    }

                    Assert.Equal(expectedFlags, allFlags);
                }
        }
 private static bool VerifyChainStatus(X509ChainStatus[] chainStatusArray)
 {
     if (chainStatusArray.Length == 1)
     {
         X509ChainStatusFlags chainStatus = chainStatusArray.First().Status;
         return(chainStatus == X509ChainStatusFlags.NoError || chainStatus == X509ChainStatusFlags.UntrustedRoot || chainStatus == X509ChainStatusFlags.PartialChain);
     }
     return(false);
 }
Example #28
0
        public static void BuildInvalidSignatureTwice()
        {
            byte[] bytes = (byte[])TestData.MsCertificate.Clone();
            bytes[bytes.Length - 1] ^= 0xFF;

            using (X509Certificate2 cert = new X509Certificate2(bytes))
                using (ChainHolder chainHolder = new ChainHolder())
                {
                    X509Chain chain = chainHolder.Chain;
                    chain.ChainPolicy.VerificationTime  = cert.NotBefore.AddHours(2);
                    chain.ChainPolicy.VerificationFlags =
                        X509VerificationFlags.AllowUnknownCertificateAuthority;

                    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

                    int iter = 0;

                    void CheckChain()
                    {
                        iter++;
                        bool valid = chain.Build(cert);
                        X509ChainStatusFlags allFlags = chain.AllStatusFlags();

                        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                        {
                            // OSX considers this to be valid because it doesn't report NotSignatureValid,
                            // just PartialChain ("I couldn't find an issuer that made the signature work"),
                            // and PartialChain + AllowUnknownCertificateAuthority == pass.
                            Assert.True(valid, $"Chain is valid on execution {iter}");

                            Assert.Equal(1, chain.ChainElements.Count);

                            Assert.Equal(
                                X509ChainStatusFlags.PartialChain,
                                allFlags);
                        }
                        else
                        {
                            Assert.False(valid, $"Chain is valid on execution {iter}");

                            Assert.Equal(3, chain.ChainElements.Count);

                            // Clear UntrustedRoot, if it happened.
                            allFlags &= ~X509ChainStatusFlags.UntrustedRoot;

                            Assert.Equal(
                                X509ChainStatusFlags.NotSignatureValid,
                                allFlags);
                        }

                        chainHolder.DisposeChainElements();
                    }

                    CheckChain();
                    CheckChain();
                }
        }
Example #29
0
 private bool IsValid(X509Certificate cert)
 {
     if (!cert.IsCurrent)
     {
         this._status = X509ChainStatusFlags.NotTimeNested;
         return(false);
     }
     return(true);
 }
 private void Set(X509ChainStatus[] status, ref int position, X509ChainStatusFlags flags, X509ChainStatusFlags mask)
 {
     if ((flags & mask) != 0)
     {
         status[position].Status            = mask;
         status[position].StatusInformation = X509ChainStatus.GetInformation(mask);
         position++;
     }
 }
Example #31
0
        private void CheckRevocationOnChain(X509ChainStatusFlags flag)
        {
            bool flag2 = (flag & X509ChainStatusFlags.PartialChain) != X509ChainStatusFlags.NoError;
            bool online;

            switch (this.ChainPolicy.RevocationMode)
            {
            case X509RevocationMode.NoCheck:
                return;

            case X509RevocationMode.Online:
                online = true;
                break;

            case X509RevocationMode.Offline:
                online = false;
                break;

            default:
                throw new InvalidOperationException(Locale.GetText("Invalid revocation mode."));
            }
            bool flag3 = flag2;

            for (int i = this.elements.Count - 1; i >= 0; i--)
            {
                bool flag4 = true;
                switch (this.ChainPolicy.RevocationFlag)
                {
                case X509RevocationFlag.EndCertificateOnly:
                    flag4 = (i == 0);
                    break;

                case X509RevocationFlag.EntireChain:
                    flag4 = true;
                    break;

                case X509RevocationFlag.ExcludeRoot:
                    flag4 = (i != this.elements.Count - 1);
                    break;
                }
                X509ChainElement x509ChainElement = this.elements[i];
                if (!flag3)
                {
                    flag3 |= ((x509ChainElement.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != X509ChainStatusFlags.NoError);
                }
                if (flag3)
                {
                    x509ChainElement.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
                    x509ChainElement.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
                }
                else if (flag4 && !flag2 && !this.IsSelfIssued(x509ChainElement.Certificate))
                {
                    x509ChainElement.StatusFlags |= this.CheckRevocation(x509ChainElement.Certificate, i + 1, online);
                    flag3 |= ((x509ChainElement.StatusFlags & X509ChainStatusFlags.Revoked) != X509ChainStatusFlags.NoError);
                }
            }
        }
Example #32
0
		// this method avoid having a dependance on the order of status
		public void CheckChainStatus (X509ChainStatusFlags expected, X509ChainStatus[] status, string msg)
		{
			if ((expected == X509ChainStatusFlags.NoError) && (status.Length == 0))
				return;

			X509ChainStatusFlags actual = X509ChainStatusFlags.NoError;
			foreach (X509ChainStatus s in status) {
				actual |= s.Status;
			}
			Assert.AreEqual (expected, actual, msg);
		}
Example #33
0
        public static X509Certificate2Collection FilterValidCerts(
            X509Certificate2Collection certs, 
            X509ChainPolicy policy, 
            X509ChainStatusFlags problemFlags,
            Action<Exception> notification)
        {
            var validCerts = new X509Certificate2Collection();
            if (certs == null) return null;
            foreach (var cert in certs)
            {
                X509Chain chainBuilder = new X509Chain();
                chainBuilder.ChainPolicy = policy.Clone();

                try
                {
                    // We're using the system class as a helper to merely build the chain
                    // However, we will review each item in the chain ourselves, because we have our own rules...
                    chainBuilder.Build(cert);
                    X509ChainElementCollection chainElements = chainBuilder.ChainElements;

                    // If we don't have a trust chain, then we obviously have a problem...
                    if (chainElements.IsNullOrEmpty())
                    {
                        notification(new Exception(string.Format("Can't find a trust chain: {0} ", cert.Subject)));
                        return null;
                    }


                    // walk the chain starting at the leaf and see if we hit any issues before the anchor
                    foreach (X509ChainElement chainElement in chainElements)
                    {
                        if (ChainElementHasProblems(chainElement, problemFlags))
                        {
                            //this.NotifyProblem(chainElement);

                            notification(new Exception(string.Format("Chain Element has problem {0}", Summarize(chainElement, problemFlags))));
                            // Whoops... problem with at least one cert in the chain. Stop immediately
                            return null;
                        }
                    }
                }
                catch (Exception ex)
                {
                    //this.NotifyError(certificate, ex);
                    // just eat it and drop out to return null
                    notification(ex);
                    return null;
                }
                validCerts.Add(cert);
            }
            return validCerts;
        }
Example #34
0
		private int Count (X509ChainStatusFlags flags)
		{
			int size = 0;
			int n = 0;
			int f = (int) flags;
			int m = 0x1;
			while (n++ < 32) {
				if ((f & m) == m)
					size++;
				m <<= 1;
			}
			return size;
		}
Example #35
0
        static bool ChainElementHasProblems(X509ChainElement chainElement, X509ChainStatusFlags problemFlags)
        {
            // If the builder finds problems with the cert, it will provide a list of "status" flags for the cert
            X509ChainStatus[] chainElementStatus = chainElement.ChainElementStatus;

            // If the list is empty or the list is null, then there were NO problems with the cert
            if (chainElementStatus.IsNullOrEmpty())
            {
                return false;
            }

            // Return true if there are any status flags we care about
            return chainElementStatus.Any(s => (s.Status & problemFlags) != 0);
        }
Example #36
0
 /// <summary>
 /// Creates a new instance of the <see cref="SimplePolicyChecker"/> class.
 /// </summary>
 public SimplePolicyChecker()
 {
     m_validPolicyErrors = SslPolicyErrors.None;
     m_validChainFlags = X509ChainStatusFlags.NoError;
 }
Example #37
0
 /// <summary>
 /// Creates an instance, specifying chain policy and problem flags
 /// </summary>
 /// <param name="policy">The <see cref="X509ChainPolicy"/> to use for validating trust chains</param>
 /// <param name="problemFlags">The status flags that will be treated as invalid in trust verification</param>
 public TrustChainValidator(X509ChainPolicy policy, X509ChainStatusFlags problemFlags)
 {
     m_policy = policy;
     m_problemFlags = problemFlags;
 }
Example #38
0
 /// <summary>
 /// Creates a new instance of the <see cref="CertificatePolicy"/> class.
 /// </summary>
 public CertificatePolicy()
 {
     m_validPolicyErrors = SslPolicyErrors.None;
     m_validChainFlags = X509ChainStatusFlags.NoError;
 }
		internal X509ChainStatus (X509ChainStatusFlags flag)
		{
			status = flag;
			info = GetInformation (flag);
		}
		public bool Build (X509Certificate leaf) 
		{
			_status = X509ChainStatusFlags.NoError;
			if (_chain == null) {
				// chain not supplied - we must built it ourselve
				_chain = new X509CertificateCollection ();
				X509Certificate x = leaf;
				X509Certificate tmp = null;
				while ((x != null) && (!x.IsSelfSigned)) {
					tmp = FindCertificateParent (x);
					if (x != null) {
						_chain.Add (x);
						x = tmp;	// last valid
					}
				}
				// find a trusted root
				_root = FindCertificateRoot (tmp);
			}
			else {
				// chain supplied - still have to check signatures!
				int last = _chain.Count;
				if (last > 0) {
					if (IsParent (leaf, _chain [0])) {
						int i = 1;
						for (; i < last; i++) {
							if (!IsParent (_chain [i-1], _chain [i]))
								break;
						}
						if (i == last)
							_root = FindCertificateRoot (_chain [last - 1]);
					}
				}
				else {
					// is the leaf a root ? (trusted or untrusted)
					_root = FindCertificateRoot (leaf);
				}
			}

			// validate the chain
			if ((_chain != null) && (_status == X509ChainStatusFlags.NoError)) {
				foreach (X509Certificate x in _chain) {
					// validate dates for each certificate in the chain
					// note: we DO NOT check for nested date/time
					if (!IsValid (x)) {
						return false;
					}
				}
				// check leaf
				if (!IsValid (leaf)) {
					// switch status code if the failure is expiration
					if (_status == X509ChainStatusFlags.NotTimeNested)
						_status = X509ChainStatusFlags.NotTimeValid;
					return false;
				}
				// check root
				if ((_root != null) && !IsValid (_root)) {
					return false;
				}
			}
			return (_status == X509ChainStatusFlags.NoError);
		}
		// private stuff

		private bool IsValid (X509Certificate cert) 
		{
			if (!cert.IsCurrent) {
				// FIXME: nesting isn't very well implemented
				_status = X509ChainStatusFlags.NotTimeNested;
				return false;
			}

			// TODO - we should check for CRITICAL but unknown extensions
			// X509ChainStatusFlags.InvalidExtension
#if (!NET_1_0 && !INSIDE_CORLIB)
			if (ServicePointManager.CheckCertificateRevocationList) {
				// TODO - check revocation (CRL, OCSP ...)
				// X509ChainStatusFlags.RevocationStatusUnknown
				// X509ChainStatusFlags.Revoked
			}
#endif
			return true;
		}
Example #42
0
        /// <summary>
        /// Initializes <see cref="DataSubscriber"/>.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            Dictionary<string, string> settings = Settings;
            string setting;

            OperationalModes operationalModes;
            CompressionModes compressionModes;
            int metadataSynchronizationTimeout;
            double interval;
            int bufferSize;

            // Setup connection to data publishing server with or without authentication required
            if (settings.TryGetValue("requireAuthentication", out setting))
                RequireAuthentication = setting.ParseBoolean();

            // See if user has opted for different operational modes
            if (settings.TryGetValue("operationalModes", out setting) && Enum.TryParse(setting, true, out operationalModes))
                OperationalModes = operationalModes;

            // Set the security mode if explicitly defined
            if (!settings.TryGetValue("securityMode", out setting) || !Enum.TryParse(setting, true, out m_securityMode))
                m_securityMode = SecurityMode.None;

            // Apply gateway compression mode to operational mode flags
            if (settings.TryGetValue("compressionModes", out setting) && Enum.TryParse(setting, true, out compressionModes))
                CompressionModes = compressionModes;

            if (settings.TryGetValue("useZeroMQChannel", out setting))
                m_useZeroMQChannel = setting.ParseBoolean();

            // TODO: Remove this exception when CURVE is enabled in GSF ZeroMQ library
            if (m_useZeroMQChannel && m_securityMode == SecurityMode.TLS)
                throw new ArgumentException("CURVE security settings are not yet available for GSF ZeroMQ client channel.");

            // Settings specific to Gateway security
            if (m_securityMode == SecurityMode.Gateway)
            {
                if (!settings.TryGetValue("sharedSecret", out m_sharedSecret) || string.IsNullOrWhiteSpace(m_sharedSecret))
                    throw new ArgumentException("The \"sharedSecret\" setting must be defined when using Gateway security mode.");

                if (!settings.TryGetValue("authenticationID", out m_authenticationID) || string.IsNullOrWhiteSpace(m_authenticationID))
                    throw new ArgumentException("The \"authenticationID\" setting must be defined when using Gateway security mode.");
            }

            // Settings specific to Transport Layer Security
            if (m_securityMode == SecurityMode.TLS)
            {
                if (!settings.TryGetValue("localCertificate", out m_localCertificate) || !File.Exists(m_localCertificate))
                    m_localCertificate = GetLocalCertificate();

                if (!settings.TryGetValue("remoteCertificate", out m_remoteCertificate) || !RemoteCertificateExists())
                    throw new ArgumentException("The \"remoteCertificate\" setting must be defined and certificate file must exist when using TLS security mode.");

                if (!settings.TryGetValue("validPolicyErrors", out setting) || !Enum.TryParse(setting, out m_validPolicyErrors))
                    m_validPolicyErrors = SslPolicyErrors.None;

                if (!settings.TryGetValue("validChainFlags", out setting) || !Enum.TryParse(setting, out m_validChainFlags))
                    m_validChainFlags = X509ChainStatusFlags.NoError;

                if (settings.TryGetValue("checkCertificateRevocation", out setting) && !string.IsNullOrWhiteSpace(setting))
                    m_checkCertificateRevocation = setting.ParseBoolean();
                else
                    m_checkCertificateRevocation = true;
            }

            // Check if measurements for this connection should be marked as "internal" - i.e., owned and allowed for proxy
            if (settings.TryGetValue("internal", out setting))
                m_internal = setting.ParseBoolean();

            // Check if user has explicitly defined the ReceiveInternalMetadata flag
            if (settings.TryGetValue("receiveInternalMetadata", out setting))
                ReceiveInternalMetadata = setting.ParseBoolean();

            // Check if user has explicitly defined the ReceiveExternalMetadata flag
            if (settings.TryGetValue("receiveExternalMetadata", out setting))
                ReceiveExternalMetadata = setting.ParseBoolean();

            // Check if user has defined a meta-data synchronization timeout
            if (settings.TryGetValue("metadataSynchronizationTimeout", out setting) && int.TryParse(setting, out metadataSynchronizationTimeout))
                m_metadataSynchronizationTimeout = metadataSynchronizationTimeout;

            // Check if user has defined a flag for using a transaction during meta-data synchronization
            if (settings.TryGetValue("useTransactionForMetadata", out setting))
                m_useTransactionForMetadata = setting.ParseBoolean();

            // Check if user wants to request that publisher use millisecond resolution to conserve bandwidth
            if (settings.TryGetValue("useMillisecondResolution", out setting))
                m_useMillisecondResolution = setting.ParseBoolean();

            // Check if user wants to request that publisher remove NaN from the data stream to conserve bandwidth
            if (settings.TryGetValue("requestNaNValueFilter", out setting))
                m_requestNaNValueFilter = setting.ParseBoolean();

            // Check if user has defined any meta-data filter expressions
            if (settings.TryGetValue("metadataFilters", out setting))
                m_metadataFilters = setting;

            // Define auto connect setting
            if (settings.TryGetValue("autoConnect", out setting))
            {
                m_autoConnect = setting.ParseBoolean();

                if (m_autoConnect)
                    m_autoSynchronizeMetadata = true;
            }

            // Define the maximum allowed exceptions before resetting the connection
            if (settings.TryGetValue("allowedParsingExceptions", out setting))
                m_allowedParsingExceptions = int.Parse(setting);

            // Define the window of time over which parsing exceptions are tolerated
            if (settings.TryGetValue("parsingExceptionWindow", out setting))
                m_parsingExceptionWindow = Ticks.FromSeconds(double.Parse(setting));

            // Check if synchronize meta-data is explicitly enabled or disabled
            if (settings.TryGetValue("synchronizeMetadata", out setting))
                m_autoSynchronizeMetadata = setting.ParseBoolean();

            // Define data loss interval
            if (settings.TryGetValue("dataLossInterval", out setting) && double.TryParse(setting, out interval))
                DataLossInterval = interval;

            // Define buffer size
            if (!settings.TryGetValue("bufferSize", out setting) || !int.TryParse(setting, out bufferSize))
                bufferSize = ClientBase.DefaultReceiveBufferSize;

            if (settings.TryGetValue("useLocalClockAsRealTime", out setting))
                m_useLocalClockAsRealTime = setting.ParseBoolean();

            if (m_autoConnect)
            {
                // Connect to local events when automatically engaging connection cycle
                ConnectionAuthenticated += DataSubscriber_ConnectionAuthenticated;
                MetaDataReceived += DataSubscriber_MetaDataReceived;

                // Update output measurements to include "subscribed" points
                UpdateOutputMeasurements(true);
            }
            else if (m_autoSynchronizeMetadata)
            {
                // Output measurements do not include "subscribed" points,
                // but should still be filtered if applicable
                TryFilterOutputMeasurements();
            }

            if (m_securityMode != SecurityMode.TLS)
            {
                if (m_useZeroMQChannel)
                {
                    // Create a new ZeroMQ Dealer
                    ZeroMQClient commandChannel = new ZeroMQClient();

                    // Initialize default settings
                    commandChannel.PersistSettings = false;
                    commandChannel.MaxConnectionAttempts = 1;
                    commandChannel.ReceiveBufferSize = bufferSize;
                    commandChannel.SendBufferSize = bufferSize;

                    // Assign command channel client reference and attach to needed events
                    CommandChannel = commandChannel;
                }
                else
                {
                    // Create a new TCP client
                    TcpClient commandChannel = new TcpClient();

                    // Initialize default settings
                    commandChannel.PayloadAware = true;
                    commandChannel.PersistSettings = false;
                    commandChannel.MaxConnectionAttempts = 1;
                    commandChannel.ReceiveBufferSize = bufferSize;
                    commandChannel.SendBufferSize = bufferSize;

                    // Assign command channel client reference and attach to needed events
                    CommandChannel = commandChannel;
                }
            }
            else
            {
                if (m_useZeroMQChannel)
                {
                    // Create a new ZeroMQ Dealer with CURVE security enabled
                    ZeroMQClient commandChannel = new ZeroMQClient();

                    // Initialize default settings
                    commandChannel.PersistSettings = false;
                    commandChannel.MaxConnectionAttempts = 1;
                    commandChannel.ReceiveBufferSize = bufferSize;
                    commandChannel.SendBufferSize = bufferSize;

                    // TODO: Parse certificate and pass keys to ZeroMQClient for CURVE security

                    // Assign command channel client reference and attach to needed events
                    CommandChannel = commandChannel;
                }
                else
                {
                    // Create a new TLS client and certificate checker
                    TlsClient commandChannel = new TlsClient();
                    SimpleCertificateChecker certificateChecker = new SimpleCertificateChecker();

                    // Set up certificate checker
                    certificateChecker.TrustedCertificates.Add(new X509Certificate2(FilePath.GetAbsolutePath(m_remoteCertificate)));
                    certificateChecker.ValidPolicyErrors = m_validPolicyErrors;
                    certificateChecker.ValidChainFlags = m_validChainFlags;

                    // Initialize default settings
                    commandChannel.PayloadAware = true;
                    commandChannel.PersistSettings = false;
                    commandChannel.MaxConnectionAttempts = 1;
                    commandChannel.CertificateFile = FilePath.GetAbsolutePath(m_localCertificate);
                    commandChannel.CheckCertificateRevocation = m_checkCertificateRevocation;
                    commandChannel.CertificateChecker = certificateChecker;
                    commandChannel.ReceiveBufferSize = bufferSize;
                    commandChannel.SendBufferSize = bufferSize;

                    // Assign command channel client reference and attach to needed events
                    CommandChannel = commandChannel;
                }
            }

            // Get proper connection string - either from specified command channel or from base connection string
            if (settings.TryGetValue("commandChannel", out setting))
                m_commandChannel.ConnectionString = setting;
            else
                m_commandChannel.ConnectionString = ConnectionString;

            // Get logging path, if any has been defined
            if (settings.TryGetValue("loggingPath", out setting))
            {
                setting = FilePath.GetDirectoryName(FilePath.GetAbsolutePath(setting));

                if (Directory.Exists(setting))
                    m_loggingPath = setting;
                else
                    OnStatusMessage("WARNING: Logging path \"{0}\" not found, defaulting to \"{1}\"...", setting, FilePath.GetAbsolutePath(""));
            }

            // Initialize data gap recovery processing, if requested
            if (settings.TryGetValue("dataGapRecovery", out setting))
            {
                // Make sure setting exists to allow user to by-pass phasor data source validation at startup
                ConfigurationFile configFile = ConfigurationFile.Current;
                CategorizedSettingsElementCollection systemSettings = configFile.Settings["systemSettings"];
                CategorizedSettingsElement dataGapRecoveryEnabledSetting = systemSettings["DataGapRecoveryEnabled"];

                // See if this node should process phasor source validation
                if ((object)dataGapRecoveryEnabledSetting == null || dataGapRecoveryEnabledSetting.ValueAsBoolean())
                {
                    // Example connection string for data gap recovery:
                    //  dataGapRecovery={enabled=true; recoveryStartDelay=10.0; minimumRecoverySpan=0.0; maximumRecoverySpan=3600.0}
                    Dictionary<string, string> dataGapSettings = setting.ParseKeyValuePairs();

                    if (dataGapSettings.TryGetValue("enabled", out setting) && setting.ParseBoolean())
                    {
                        // Remove dataGapRecovery connection setting from command channel connection string, if defined there.
                        // This will prevent any recursive data gap recovery operations from being established:
                        Dictionary<string, string> connectionSettings = m_commandChannel.ConnectionString.ParseKeyValuePairs();
                        connectionSettings.Remove("dataGapRecovery");
                        connectionSettings.Remove("autoConnect");
                        connectionSettings.Remove("synchronizeMetadata");
                        connectionSettings.Remove("outputMeasurements");

                        // Note that the data gap recoverer will connect on the same command channel port as
                        // the real-time subscriber (TCP only)
                        m_dataGapRecoveryEnabled = true;
                        m_dataGapRecoverer = new DataGapRecoverer();
                        m_dataGapRecoverer.SourceConnectionName = Name;
                        m_dataGapRecoverer.DataSource = DataSource;
                        m_dataGapRecoverer.ConnectionString = string.Join("; ", $"autoConnect=false; synchronizeMetadata=false{(string.IsNullOrWhiteSpace(m_loggingPath) ? "" : "; loggingPath=" + m_loggingPath)}", dataGapSettings.JoinKeyValuePairs(), connectionSettings.JoinKeyValuePairs());
                        m_dataGapRecoverer.FilterExpression = this.OutputMeasurementKeys().Select(key => key.SignalID.ToString()).ToDelimitedString(';');
                        m_dataGapRecoverer.RecoveredMeasurements += m_dataGapRecoverer_RecoveredMeasurements;
                        m_dataGapRecoverer.StatusMessage += m_dataGapRecoverer_StatusMessage;
                        m_dataGapRecoverer.ProcessException += m_dataGapRecoverer_ProcessException;
                        m_dataGapRecoverer.Initialize();
                    }
                    else
                    {
                        m_dataGapRecoveryEnabled = false;
                    }
                }
            }
            else
            {
                m_dataGapRecoveryEnabled = false;
            }

            // Register subscriber with the statistics engine
            StatisticsEngine.Register(this, "Subscriber", "SUB");
            StatisticsEngine.Calculated += (sender, args) => ResetMeasurementsPerSecondCounters();

            Initialized = true;
        }
Example #43
0
		// *** certificate chain/path validation stuff ***

		// Currently a subset of RFC3280 (hopefully a full implementation someday)
		private void ValidateChain (X509ChainStatusFlags flag)
		{
			// 'n' should be the root certificate... 
			int n = elements.Count - 1;
			X509Certificate2 certificate = elements [n].Certificate;

			// ... and, if so, must be treated outside the chain... 
			if (((flag & X509ChainStatusFlags.PartialChain) == 0)) {
				Process (n);
				// deal with the case where the chain == the root certificate 
				// (which isn't for RFC3280) part of the chain
				if (n == 0) {
					elements [0].UncompressFlags ();
					return;
				}
				// skip the root certificate when processing the chain (in 6.1.3)
				n--;
			}
			// ... unless the chain is a partial one (then we start with that one)

			// 6.1.1 - Inputs
			// 6.1.1.a - a prospective certificate path of length n (i.e. elements)
			// 6.1.1.b - the current date/time (i.e. ChainPolicy.VerificationTime)
			// 6.1.1.c - user-initial-policy-set (i.e. ChainPolicy.CertificatePolicy)
			// 6.1.1.d - the trust anchor information (i.e. certificate, unless it's a partial chain)
			// 6.1.1.e - initial-policy-mapping-inhibit (NOT SUPPORTED BY THE API)
			// 6.1.1.f - initial-explicit-policy (NOT SUPPORTED BY THE API)
			// 6.1.1.g - initial-any-policy-inhibit (NOT SUPPORTED BY THE API)

			// 6.1.2 - Initialization (incomplete)
			// 6.1.2.a-f - policy stuff, some TODO, some not supported
			// 6.1.2.g - working public key algorithm
//			working_public_key_algorithm = certificate.PublicKey.Oid.Value;
			// 6.1.2.h-i - our key contains both the "working public key" and "working public key parameters" data
			working_public_key = certificate.PublicKey.Key;
			// 6.1.2.j - working issuer name
			working_issuer_name = certificate.IssuerName;
			// 6.1.2.k - this integer is initialized to n, is decremented for each non-self-issued, certificate and
			//	     may be reduced to the value in the path length constraint field
			max_path_length = n;

			// 6.1.3 - Basic Certificate Processing
			// note: loop looks reversed (the list is) but we process this part just like RFC3280 does
			for (int i = n; i > 0; i--) {
				Process (i);
				// 6.1.4 - preparation for certificate i+1 (for not with i+1, or i-1 in our loop)
				PrepareForNextCertificate (i);
			}
			Process (0);

			// 6.1.3.a.3 - revocation checks
			CheckRevocationOnChain (flag);

			// 6.1.5 - Wrap-up procedure
			WrapUp ();
		}
Example #44
0
        //this code comes from AgentDiagnostics.  Need a better way to hook ino Agent.
        //Agent hooks TrustChainValidator and the build in DnsCertResolver, but the DnsCertResolver is strongly 
        //linked rather than via interface for notifications and exceptions.
        static string Summarize(X509ChainElement chainElement, X509ChainStatusFlags problemFlags)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(chainElement.Certificate.ExtractEmailNameOrName());
            builder.Append(";");
            foreach (X509ChainStatus status in chainElement.ChainElementStatus)
            {
                if ((status.Status & problemFlags) != 0)
                {
                    builder.Append(status.Status);
                }
            }

            return builder.ToString();
        }
		private bool IsParent (X509Certificate child, X509Certificate parent) 
		{
			if (child.IssuerName != parent.SubjectName)
				return false;

			// parent MUST have the Basic Constraint CA=true (except for trusted roots)
			// see why at http://www.microsoft.com/technet/security/bulletin/MS02-050.asp
			if ((parent.Version > 2) && (!IsTrusted (parent))) {
				// TODO: we do not support pathLenConstraint
				X509Extension ext = parent.Extensions ["2.5.29.19"];
				if (ext != null) {
					BasicConstraintsExtension bc = new BasicConstraintsExtension (ext);
					if (!bc.CertificateAuthority)
						_status = X509ChainStatusFlags.InvalidBasicConstraints;
				}
				else
					_status = X509ChainStatusFlags.InvalidBasicConstraints;
			}

			if (!child.VerifySignature (parent.RSA)) {
				_status = X509ChainStatusFlags.NotSignatureValid;
				return false;
			}
			return true;
		}
		private X509Certificate FindCertificateRoot (X509Certificate potentialRoot) 
		{
			if (potentialRoot == null) {
				_status = X509ChainStatusFlags.PartialChain;
				return null;
			}

			// if the trusted root is in the chain
			if (IsTrusted (potentialRoot)) {
				return potentialRoot;
			}

			// if the root isn't in the chain
			foreach (X509Certificate root in TrustAnchors) {
				if (IsParent (potentialRoot, root)) {
					return root;
				}
			}

			// is it a (untrusted) root ?
			if (potentialRoot.IsSelfSigned) {
				_status = X509ChainStatusFlags.UntrustedRoot;
				return potentialRoot;
			}

			_status = X509ChainStatusFlags.PartialChain;
			return null;
		}
        /// <summary>
        /// Create an LDAP certificate resolver, using timeout and default DNS server for SRV lookup
        /// </summary>
        /// <param name="dnsServerIp">An <see cref="IPAddress"/> IP address of the DNS server to use for DNS lookups</param>
        /// <param name="timeout">Timeout value for DNS and LDAP lookups</param>
        /// <param name="cacheEnabled">boolean flag indicating whether or not to use the DNS client with cache</param>
        public LdapCertResolver(IPAddress dnsServerIp, TimeSpan timeout, bool cacheEnabled)
        {
            if (dnsServerIp == null)
            {
                dnsServerIp = GetLocalServerDns(dnsServerIp);
            }
            if (dnsServerIp == null)
                throw new ArgumentNullException("dnsServerIp");

            if (timeout.Ticks < 0)
            {
                throw new ArgumentException("timeout value was less than zero", "timeout");
            }

            m_dnsServerIp = dnsServerIp;
            m_timeout = timeout;
            m_cacheEnabled = cacheEnabled;

            m_policy = new X509ChainPolicy();
            m_policy.VerificationFlags = (X509VerificationFlags.IgnoreWrongUsage);

            m_problemFlags = DefaultProblemFlags;

        }
 public X509ChainErrorMapping(CertTrustErrorStatus win32Flag, int win32ErrorCode, X509ChainStatusFlags chainStatusFlag)
 {
     Win32Flag = win32Flag;
     Win32ErrorCode = win32ErrorCode;
     ChainStatusFlag = chainStatusFlag;
 }
Example #49
0
 /// <summary>
 /// Creates a new instance of the <see cref="SimpleCertificateChecker"/> class.
 /// </summary>
 public SimpleCertificateChecker()
 {
     m_trustedCertificates = new List<X509Certificate>();
     m_validPolicyErrors = SslPolicyErrors.None;
     m_validChainFlags = X509ChainStatusFlags.NoError;
 }
        private static X509VerificationFlags? GetSuppressionFlag(X509ChainStatusFlags status)
        {
            switch (status)
            {
                case X509ChainStatusFlags.UntrustedRoot:
                case X509ChainStatusFlags.PartialChain:
                    return X509VerificationFlags.AllowUnknownCertificateAuthority;

                case X509ChainStatusFlags.NotValidForUsage:
                case X509ChainStatusFlags.CtlNotValidForUsage:
                    return X509VerificationFlags.IgnoreWrongUsage;

                case X509ChainStatusFlags.NotTimeValid:
                    return X509VerificationFlags.IgnoreNotTimeValid;

                case X509ChainStatusFlags.CtlNotTimeValid:
                    return X509VerificationFlags.IgnoreCtlNotTimeValid;

                case X509ChainStatusFlags.InvalidNameConstraints:
                case X509ChainStatusFlags.HasNotSupportedNameConstraint:
                case X509ChainStatusFlags.HasNotDefinedNameConstraint:
                case X509ChainStatusFlags.HasNotPermittedNameConstraint:
                case X509ChainStatusFlags.HasExcludedNameConstraint:
                    return X509VerificationFlags.IgnoreInvalidName;

                case X509ChainStatusFlags.InvalidPolicyConstraints:
                case X509ChainStatusFlags.NoIssuanceChainPolicy:
                    return X509VerificationFlags.IgnoreInvalidPolicy;

                case X509ChainStatusFlags.InvalidBasicConstraints:
                    return X509VerificationFlags.IgnoreInvalidBasicConstraints;

                case X509ChainStatusFlags.HasNotSupportedCriticalExtension:
                    // This field would be mapped in by AllFlags, but we don't have a name for it currently.
                    return (X509VerificationFlags)0x00002000;

                case X509ChainStatusFlags.NotTimeNested:
                    return X509VerificationFlags.IgnoreNotTimeNested;
            }

            return null;
        }
Example #51
0
		private void Set (X509ChainStatus[] status, ref int position, X509ChainStatusFlags flags, X509ChainStatusFlags mask)
		{
			if ((flags & mask) != 0) {
				status [position].Status = mask;
				status [position].StatusInformation = X509ChainStatus.GetInformation (mask);
				position++;
			}
		}
		//

		public void Reset () 
		{
			_status = X509ChainStatusFlags.NoError;
			roots = null; // this force a reload
			certs.Clear ();
			if (_chain != null)
				_chain.Clear ();
		}
Example #53
0
		// we check the revocation only once we have built the complete chain
		private void CheckRevocationOnChain (X509ChainStatusFlags flag)
		{
			bool partial = ((flag & X509ChainStatusFlags.PartialChain) != 0);
			bool online;

			switch (ChainPolicy.RevocationMode) {
			case X509RevocationMode.Online:
				// default
				online = true;
				break;
			case X509RevocationMode.Offline:
				online = false;
				break;
			case X509RevocationMode.NoCheck:
				return;
			default:
				throw new InvalidOperationException (Locale.GetText ("Invalid revocation mode."));
			}

			bool unknown = partial;
			// from the root down to the end-entity
			for (int i = elements.Count - 1; i >= 0; i--) {
				bool check = true;

				switch (ChainPolicy.RevocationFlag) {
				case X509RevocationFlag.EndCertificateOnly:
					check = (i == 0);
					break;
				case X509RevocationFlag.EntireChain:
					check = true;
					break;
				case X509RevocationFlag.ExcludeRoot:
					// default
					check = (i != (elements.Count - 1));
					// anyway, who's gonna sign that the root is invalid ?
					break;
				}

				X509ChainElement element = elements [i];

				// we can't assume the revocation status if the certificate is bad (e.g. invalid signature)
				if (!unknown)
					unknown |= ((element.StatusFlags & X509ChainStatusFlags.NotSignatureValid) != 0);

				if (unknown) {
					// we can skip the revocation checks as we can't be sure of them anyway
					element.StatusFlags |= X509ChainStatusFlags.RevocationStatusUnknown;
					element.StatusFlags |= X509ChainStatusFlags.OfflineRevocation;
				} else if (check && !partial && !IsSelfIssued (element.Certificate)) {
					// check for revocation (except for the trusted root and self-issued certs)
					element.StatusFlags |= CheckRevocation (element.Certificate, i+1, online);
					// if revoked, then all others following in the chain are unknown...
					unknown |= ((element.StatusFlags & X509ChainStatusFlags.Revoked) != 0);
				}
			}
		}
        /// <summary>
        /// Creates a DNS certificate resolver with a custom timeout and a fallback domain.
        /// </summary>
        /// <param name="serverIP">An <see cref="IPAddress"/> instance providing the IP address of the DNS server</param>
        /// <param name="timeout">Timeout value</param>
        /// <param name="fallbackDomain">A fallback domain name to try if the main domain name is not resolved.</param>
        /// <param name="cacheEnabled">boolean flag indicating whether or not to use the client with cache</param>
        public DnsCertResolver(IPAddress serverIP
                               , TimeSpan timeout
                               , string fallbackDomain
                               , bool cacheEnabled)
        {
            if (serverIP == null)
            {
                throw new ArgumentNullException("serverIP");
            }
            if (timeout.Ticks < 0)
            {
                throw new ArgumentException("timeout value was less than zero", "timeout");
            }

            m_serverIP = serverIP;
            m_timeout = timeout;
            m_fallbackDomain = fallbackDomain;
            m_cacheEnabled = cacheEnabled;

            m_policy = new X509ChainPolicy();
            m_policy.VerificationFlags = (X509VerificationFlags.IgnoreWrongUsage);

            m_problemFlags = DefaultProblemFlags;
        }