Example #1
0
        /// <summary>
        /// returns the SSL wrapper flags for the given configuration
        /// </summary>
        /// <param name="mustCheckCertificateRevocation">if true, it indicates that the certificate revocation must be verified</param>
        /// <param name="mustCheckCertificateTrustChain">if true, it indicates that the certificate chain must be verified</param>
        /// <returns>the SSL wrapper validation flags</returns>
        public static CertificateRulesFlags GetFlags(bool mustCheckCertificateRevocation, bool mustCheckCertificateTrustChain)
        {
            CertificateRulesFlags result = CertificateRulesFlags.None;

            if (mustCheckCertificateRevocation)
            {
                result |= CertificateRulesFlags.MustCheckCertificateRevocation;
            }

            if (mustCheckCertificateTrustChain)
            {
                result |= CertificateRulesFlags.MustCheckCertificateTrustChain;
            }

            return(result);
        }
Example #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CertificateValidator"/> class.
        /// </summary>
        /// <param name="identities">identities for this object</param>
        /// <param name="flags">flags for the SSL wrapper</param>
        /// <param name="modifySet">action to modify the default rule set</param>
        /// <param name="instrumentation">instrumentation to use</param>
        public CertificateValidator(CertIdentities identities, CertificateRulesFlags flags, Action <StandardValidationRuleSet> modifySet, ICertificateRulesInstrumentation instrumentation)
        {
            if (identities == null)
            {
                throw new ArgumentNullException("identities");
            }

            if (instrumentation == null)
            {
                instrumentation = SslWrappingInstrumentation.NullInstrumentation;
            }

            this.instrumentation = instrumentation;

            StandardValidationRuleSet set = new StandardValidationRuleSet();

            set.AddAcceptedCertificates(AbstractCertificateRule.RoleToApply.ClientCert, identities.IsClientCertificateIncluded);
            set.AddAcceptedCertificates(AbstractCertificateRule.RoleToApply.ServerCert, identities.IsServerCertificateIncluded);

            if (identities.IsClientWithNoCertificateAllowed)
            {
                set.AddBreakGlassCertificate(AbstractCertificateRule.RoleToApply.ClientCert, null);
                set.SetChainValidationRequired(AbstractCertificateRule.RoleToApply.ClientCert, false);
            }

            if (identities.IsServerWithNoCertificateAllowed)
            {
                set.AddBreakGlassCertificate(AbstractCertificateRule.RoleToApply.ServerCert, null);
            }

            if ((flags & CertificateRulesFlags.MustCheckCertificateTrustChain) == CertificateRulesFlags.None)
            {
                set.SetChainValidationRequired(AbstractCertificateRule.RoleToApply.AllCerts, false);
            }

            if (modifySet != null)
            {
                modifySet(set);
            }

            this.extraRulesTovalidateCertificates = set.Rules;

            this.BaseRule = null;
        }
Example #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SslConnection"/> class.
        /// </summary>
        /// <param name="transportId">Unique Id of the transport associated with this policy</param>
        /// <param name="configuration">Configuration settings</param>
        public SslConnection(long transportId, Configuration configuration)
        {
            this.transportId = transportId;

            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if ((configuration.ClientCertificates != null || configuration.ServerCertificates != null) && configuration.Identities != null)
            {
                throw new ArgumentException("ClientCertificates and ServerCertificates must be null if Identities is provided");
            }

            this.configuration = configuration;
            this.identities    = configuration.Identities;

            if (this.identities == null)
            {
                X509Certificate[] clientCertificates = this.configuration.ClientCertificates;
                X509Certificate[] serverCertificates = this.configuration.ServerCertificates;

                if (!configuration.StartAsClient && (serverCertificates == null || serverCertificates.Length == 0))
                {
                    SecureTransportEventSource.Log.ServerCertificatesWereNotProvided(this.transportId);
                    throw new ArgumentException("Server certificates were not provided");
                }

                if (configuration.StartAsClient && (clientCertificates == null || clientCertificates.Length == 0))
                {
                    SecureTransportEventSource.Log.ServerCertificatesWereNotProvided(this.transportId);
                    throw new ArgumentException("Client certificates were not provided");
                }

                this.identities = new CertIdentities();
                this.identities.IsClientWithNoCertificateAllowed = clientCertificates == null && !this.FoundAnySubjectRuleMatch(configuration, AbstractCertificateRule.RoleToApply.ClientCert);

                if (clientCertificates == null)
                {
                    SecureTransportEventSource.Log.ClientCertificatesWereNotProvided(this.transportId);
                    clientCertificates = new X509Certificate[0];
                }

                if (serverCertificates == null)
                {
                    SecureTransportEventSource.Log.ServerCertificatesWereNotProvided(this.transportId);
                    serverCertificates = new X509Certificate[0];
                }

                foreach (X509Certificate serverCertificate in serverCertificates)
                {
                    if (serverCertificate != null)
                    {
                        string key = serverCertificate.GetSerialNumberString();
                        if (key != null)
                        {
                            SecureTransportEventSource.Log.SupportedServerCertificate(this.transportId, key);
                        }
                    }
                    else
                    {
                        throw new ArgumentException("One of the Server Certificates is null");
                    }
                }

                foreach (X509Certificate clientCertificate in clientCertificates)
                {
                    if (clientCertificate != null)
                    {
                        string key = clientCertificate.GetSerialNumberString();

                        if (key != null)
                        {
                            SecureTransportEventSource.Log.SupportedClientCertificate(this.transportId, key);
                        }
                    }
                    else
                    {
                        throw new ArgumentException("One of the client certificates is null");
                    }
                }

                this.identities.SetClientIdentities(clientCertificates);
                this.identities.SetServerIdentities(serverCertificates);
            }

            if (this.configuration.ExplicitRule != null)
            {
                this.certificateValidator = new CertificateValidator(this.configuration.ExplicitRule);
            }
            else
            {
                CertificateRulesFlags flags = CertificateValidator.GetFlags(this.configuration.MustCheckCertificateRevocation, this.configuration.MustCheckCertificateTrustChain);

                if (this.configuration.SubjectValidations == null || this.configuration.SubjectValidations.Count == 0)
                {
                    this.certificateValidator = new CertificateValidator(this.identities, flags);
                }
                else
                {
                    Action <StandardValidationRuleSet> modifySet = (s) =>
                    {
                        foreach (SecureTransport.SubjectRuleValidation subjectRule in this.configuration.SubjectValidations)
                        {
                            s.AddAcceptedCertificateSubject(
                                subjectRule.Role,
                                subjectRule.SubjectValidation.CertificateSubject,
                                subjectRule.SubjectValidation.SigningCertThumbprints);
                        }

                        if (this.configuration.BlacklistedThumbprints != null)
                        {
                            foreach (string blacklisted in this.configuration.BlacklistedThumbprints)
                            {
                                s.AddBlacklistedCertificateThumbprint(AbstractCertificateRule.RoleToApply.AllCerts, blacklisted);
                            }
                        }
                    };

                    this.certificateValidator = new CertificateValidator(this.identities, flags, modifySet);
                }
            }
        }
Example #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CertificateValidator"/> class.
 /// </summary>
 /// <param name="identities">identities for this object</param>
 /// <param name="flags">flags for the SSL wrapper</param>
 /// <param name="instrumentation">instrumentation to use</param>
 public CertificateValidator(CertIdentities identities, CertificateRulesFlags flags, ICertificateRulesInstrumentation instrumentation = null)
     : this(identities, flags, null, instrumentation)
 {
 }
Example #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CertificateValidator"/> class.
 /// </summary>
 /// <param name="identities">identities for this object</param>
 /// <param name="flags">flags for the SSL wrapper</param>
 /// <param name="modifySet">action to modify the default rule set</param>
 public CertificateValidator(CertIdentities identities, CertificateRulesFlags flags, Action <StandardValidationRuleSet> modifySet)
     : this(identities, flags, modifySet, null)
 {
 }
Example #6
0
        /// <summary>
        /// Returns the rules built from configuration.
        /// The following are example of configuration settings:
        ///     "SSL.ClientCerts" --> example "MY/LOCALMACHINE/AF45CF47774649C6627F8CB9CDE4D5ACAE5B92F2,MY/LOCALMACHINE/1923316B5190CDEF09EF5BF1C3C491843310695A"
        ///       This setting indicates the thumbprints to be used by client as its possible identities
        ///       additionally, it tells the server what client thumbprints are allowed
        ///     "SSL.ServerCerts" --> example "MY/LOCALMACHINE/AF45CF47774649C6627F8CB9CDE4D5ACAE5B92F2,MY/LOCALMACHINE/1923316B5190CDEF09EF5BC1F3C491843310695A"
        ///       This setting indicates the thumbprint to be used in server as its identity(i.e.the first thumbprint if this is a list)
        ///       additionally, it tells the client what server thumbprints are allowed
        ///     "SSL.BlacklistedThumbprints" --> example "MY/LOCALMACHINE/4565CF47774649C6627F8CB9CDE4D5ACAE5B92F2"
        ///       This setting blacklists certain certificates by thumbprint
        ///     "SSL.BreakGlassThumbprints" --> example "MY/LOCALMACHINE/1235CF47774649C6627F8CB9CDE4D5ACAE5B92F2"
        ///       This setting break-glass certain certificates by thumbprint.
        ///     "SSL.AllowedSigningThumbprints" --> example "*,[*]"
        ///       "*" means any cert signing the given cert is okay, but the cert must be signed by a chain
        ///       "[*]" means the cert can be self-signed
        ///       "*,[*]" is equivalent to not including this setting at all, or to have it empty
        ///       Note: not including this setting at all, or to have it empty means we require the cert to be signed, but we don't 'like' any signing cert, with discards all certs not considered break-glass.
        ///     "SSL.AllowedSubjectNames" --> example "*"
        ///       "*" means any cert subject is okay.
        ///       Note: not including this setting at all, or to have it empty means we don't 'like' any cert subject, with discards all certs not considered break-glass.
        ///     "SSL.MaxValidityCertsInDays" --> example "36500"
        ///       if set, limits the maximum validity time (in days) for certificates. By default, it doesn't limit the validity time.
        ///     "SSL.RelaxValidationForTestCertificates" --> example "false"
        ///       if true, this setting allows for certificates issued for a different use, or for chains not trusted.ONLY to be used on DEV-BOX testing.
        ///       by default the value is "false"
        /// </summary>
        /// <param name="flags">the flags to be used for the SSL wrapper</param>
        /// <param name="getSettingValue">optionally, the function to retrieve config values by setting name. if not provided app.config will be used.</param>
        /// <returns>the set of validation rules from configuration.</returns>
        public static IEnumerable <AbstractCertificateRule> GetCertRulesFromConfig(out CertificateRulesFlags flags, Func <string, string> getSettingValue = null)
        {
            flags = CertificateRulesFlags.MustCheckCertificateRevocation | CertificateRulesFlags.MustCheckCertificateTrustChain;

            Func <string, string[]> getSetting = new Func <string, string[]>(
                settingName =>
            {
                try
                {
                    string setvalue = getSettingValue?.Invoke(settingName);

                    if (setvalue == null)
                    {
                        setvalue = string.Empty;
                    }

                    return(setvalue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(c => c.Trim()).ToArray());
                }
                catch (Exception)
                {
                    return(new string[0]);
                }
            });

            string[] blacklistedThumbprints    = getSetting("SSL.BlacklistedThumbprints");
            string[] breakGlassThumbprints     = getSetting("SSL.BreakGlassThumbprints");
            string[] allowedSubjectNames       = getSetting("SSL.AllowedSubjectNames");
            string[] allowedSigningThumbprints = getSetting("SSL.AllowedSigningThumbprints");

            string[] maxValidityDays = getSetting("SSL.MaxValidityCertsInDays");

            string[] relaxValidation = getSetting("SSL.RelaxValidationForTestCertificates");
            bool     relax           = false;

            if (relaxValidation.Length > 0)
            {
                if (bool.TryParse(relaxValidation[0], out relax) && relax)
                {
                    flags &= ~CertificateRulesFlags.MustCheckCertificateTrustChain;
                }
            }

            StandardValidationRuleSet set = new StandardValidationRuleSet();

            set.SetChainValidationRequired(AbstractCertificateRule.RoleToApply.AllCerts, !relax);

            foreach (string thumb in blacklistedThumbprints)
            {
                set.AddBlacklistedCertificateThumbprint(AbstractCertificateRule.RoleToApply.AllCerts, thumb);
            }

            foreach (string thumb in breakGlassThumbprints)
            {
                set.AddBreakGlassCertificateThumbprint(AbstractCertificateRule.RoleToApply.AllCerts, thumb);
            }

            if (allowedSubjectNames.Length == allowedSigningThumbprints.Length)
            {
                for (int i = 0; i < allowedSubjectNames.Length; i++)
                {
                    set.AddAcceptedCertificateSubject(AbstractCertificateRule.RoleToApply.AllCerts, allowedSubjectNames[i], allowedSigningThumbprints[i].Split(';'));
                }
            }
            else
            {
                throw new ArgumentException("configuration must have same number of allowedSubjectNames as AllowedSigningThumbprints");
            }

            // also, we don't want certificates with validity larger than n days
            if (maxValidityDays.Length > 0)
            {
                double days;

                if (double.TryParse(maxValidityDays[0], out days) && days > 0)
                {
                    set.SetMaxExpirationTime(AbstractCertificateRule.RoleToApply.AllCerts, days);
                }
            }

            return(set.Rules);
        }