예제 #1
0
 internal bool EqualsBase(DnsResourceRecord other)
 {
     return(other != null &&
            DomainName.Equals(other.DomainName) &&
            DnsType.Equals(other.DnsType) &&
            DnsClass.Equals(other.DnsClass));
 }
예제 #2
0
 /// <summary>
 /// Two DnsResourceDataUShortDomainName are equal iff their of the same type and their ushort values and domain names are equal.
 /// </summary>
 public bool Equals(DnsResourceDataUShortDomainName other)
 {
     return(other != null &&
            GetType().Equals(other.GetType()) &&
            Value.Equals(other.Value) &&
            DomainName.Equals(other.DomainName));
 }
예제 #3
0
        public void SutDoesNotEqualAnonymousObject()
        {
            // Arrange
            var sut             = new DomainName(Guid.NewGuid().ToString());
            var anonymousObject = new object();
            // Act
            bool result = sut.Equals(anonymousObject);

            // Assert
            Assert.False(result);
        }
예제 #4
0
        public void SutDoesNotEqualOtherObjectWhenDomainNamesDiffer()
        {
            // Arrange
            var    sut   = new DomainName(Guid.NewGuid().ToString());
            object other = new DomainName(Guid.NewGuid().ToString());
            // Act
            bool result = sut.Equals(other);

            // Assert
            Assert.False(result);
        }
예제 #5
0
        /// <summary>
        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            Domain domain = obj as Domain;

            if (DomainName.Equals(domain.DomainName))
            {
                return(true);
            }

            return(false);
        }
예제 #6
0
        public void SutDoesNotEqualOtherObjectWhenDomainNamesDiffer()
        {
            // Fixture setup
            var    sut   = new DomainName(Guid.NewGuid().ToString());
            object other = new DomainName(Guid.NewGuid().ToString());
            // Exercise system
            bool result = sut.Equals(other);

            // Verify outcome
            Assert.False(result);
            // Teardown
        }
예제 #7
0
        private async Task <DnsSecValidationResult> ValidateNSecAsync(DomainName name, RecordType recordType, RecordClass recordClass, List <RrSigRecord> rrSigRecords, DomainName stop, DomainName zoneApex, DnsMessageBase msg, TState state, CancellationToken token)
        {
            List <NSecRecord> nsecRecords = msg.AuthorityRecords.OfType <NSecRecord>().ToList();

            if (nsecRecords.Count == 0)
            {
                return(DnsSecValidationResult.Indeterminate);
            }

            foreach (var nsecGroup in nsecRecords.GroupBy(x => x.Name))
            {
                DnsSecValidationResult validationResult = await ValidateRrSigAsync(nsecGroup.Key, RecordType.NSec, recordClass, nsecGroup.ToList(), rrSigRecords, zoneApex, msg, state, token);

                if (validationResult != DnsSecValidationResult.Signed)
                {
                    return(validationResult);
                }
            }

            DomainName current = name;

            while (true)
            {
                if (current.Equals(stop))
                {
                    return(DnsSecValidationResult.Signed);
                }

                NSecRecord nsecRecord = nsecRecords.FirstOrDefault(x => x.Name.Equals(current));
                if (nsecRecord != null)
                {
                    return(nsecRecord.Types.Contains(recordType) ? DnsSecValidationResult.Bogus : DnsSecValidationResult.Signed);
                }
                else
                {
                    nsecRecord = nsecRecords.FirstOrDefault(x => x.IsCovering(current, zoneApex));
                    if (nsecRecord == null)
                    {
                        return(DnsSecValidationResult.Bogus);
                    }
                }

                // Updated the following lines to fix an issue where an NSEC entry is present for a parent domain but is not a wildcard entry.
                if (current.Labels[0] == "*")
                {
                    current = current.GetParentName();
                }
                else
                {
                    current = DomainName.Asterisk + current.GetParentName();
                }
            }
        }
예제 #8
0
        public void SutDoesNotEqualAnonymousObject()
        {
            // Fixture setup
            var sut             = new DomainName(Guid.NewGuid().ToString());
            var anonymousObject = new object();
            // Exercise system
            bool result = sut.Equals(anonymousObject);

            // Verify outcome
            Assert.False(result);
            // Teardown
        }
예제 #9
0
        public void SutEqualsOtherSutWhenDomainNamesAreEqual()
        {
            // Arrange
            var domainName = Guid.NewGuid().ToString();

            var sut   = new DomainName(domainName);
            var other = new DomainName(domainName);
            // Act
            bool result = sut.Equals(other);

            // Assert
            Assert.True(result);
        }
예제 #10
0
        public void SutEqualsOtherSutWhenDomainNamesAreEqual()
        {
            // Fixture setup
            var domainName = Guid.NewGuid().ToString();

            var sut   = new DomainName(domainName);
            var other = new DomainName(domainName);
            // Exercise system
            bool result = sut.Equals(other);

            // Verify outcome
            Assert.True(result);
            // Teardown
        }
예제 #11
0
        public ContainsResult Contains(Host host)
        {
            if (host.Format != HostFormat.DomainName && host.Format != HostFormat.IPv4 && host.Format != HostFormat.IPv6)
            {
                throw new ArgumentException($"Format must be {HostFormat.DomainName}, {HostFormat.IPv4}, or {HostFormat.IPv6}.");
            }

            switch (host.Format)
            {
            case HostFormat.DomainName:
                switch (Format)
                {
                case HostFormat.DomainName:
                    return(DomainName.Equals(host.DomainName, StringComparison.OrdinalIgnoreCase) ? ContainsResult.Yes : ContainsResult.No);

                case HostFormat.DomainNameSuffix:
                    return(host.DomainName.EndsWith(DomainName, StringComparison.OrdinalIgnoreCase) ? ContainsResult.Yes : ContainsResult.No);
                }
                break;

            case HostFormat.IPv4:
                switch (Format)
                {
                case HostFormat.IPv4:
                    return(IpAddress.Equals(host.IpAddress) ? ContainsResult.Yes : ContainsResult.No);

                case HostFormat.IPv4Cidr:
                    // ReSharper disable once PossibleInvalidOperationException
                    return(CidrMatches(IpAddress, host.IpAddress, MaskBits.Value, 32) ? ContainsResult.Yes : ContainsResult.No);
                }
                break;

            case HostFormat.IPv6:
                switch (Format)
                {
                case HostFormat.IPv6:
                    return(IpAddress.Equals(host.IpAddress) ? ContainsResult.Yes : ContainsResult.No);

                case HostFormat.IPv6Cidr:
                    // ReSharper disable once PossibleInvalidOperationException
                    return(CidrMatches(IpAddress, host.IpAddress, MaskBits.Value, 128) ? ContainsResult.Yes : ContainsResult.No);
                }
                break;
            }

            return(ContainsResult.Inapplicable);
        }
예제 #12
0
        public void Must_be_equatable()
        {
            DomainName a = "example.com";
            DomainName b = "example.com";
            DomainName c = "apple.com";
            DomainName d = "orange.com";

            (a == b).Should().BeTrue();
            (b == a).Should().BeTrue();
            a.Equals(b).Should().BeTrue();
            b.Equals(a).Should().BeTrue();

            (c != d).Should().BeTrue();
            (d != c).Should().BeTrue();
            c.Equals(d).Should().BeFalse();
            d.Equals(c).Should().BeFalse();
        }
        private async Task <List <T> > ResolveAsyncInternal <T>(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token)
            where T : DnsRecordBase
        {
            List <T> cachedResults;

            if (_cache.TryGetRecords(name, recordType, recordClass, out cachedResults))
            {
                return(cachedResults);
            }

            List <CNameRecord> cachedCNames;

            if (_cache.TryGetRecords(name, RecordType.CName, recordClass, out cachedCNames))
            {
                return(await ResolveAsyncInternal <T>(cachedCNames.First().CanonicalName, recordType, recordClass, state, token));
            }

            DnsMessage msg = await ResolveMessageAsync(name, recordType, recordClass, state, token);

            // check for cname
            List <DnsRecordBase> cNameRecords = msg.AnswerRecords.Where(x => (x.RecordType == RecordType.CName) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList();

            if (cNameRecords.Count > 0)
            {
                _cache.Add(name, RecordType.CName, recordClass, cNameRecords, DnsSecValidationResult.Indeterminate, cNameRecords.Min(x => x.TimeToLive));

                DomainName canonicalName = ((CNameRecord)cNameRecords.First()).CanonicalName;

                List <DnsRecordBase> matchingAdditionalRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(canonicalName)).ToList();
                if (matchingAdditionalRecords.Count > 0)
                {
                    _cache.Add(canonicalName, recordType, recordClass, matchingAdditionalRecords, DnsSecValidationResult.Indeterminate, matchingAdditionalRecords.Min(x => x.TimeToLive));
                    return(matchingAdditionalRecords.OfType <T>().ToList());
                }

                return(await ResolveAsyncInternal <T>(canonicalName, recordType, recordClass, state, token));
            }

            // check for "normal" answer
            List <DnsRecordBase> answerRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList();

            if (answerRecords.Count > 0)
            {
                _cache.Add(name, recordType, recordClass, answerRecords, DnsSecValidationResult.Indeterminate, answerRecords.Min(x => x.TimeToLive));
                return(answerRecords.OfType <T>().ToList());
            }

            // check for negative answer
            SoaRecord soaRecord = msg.AuthorityRecords
                                  .Where(x =>
                                         (x.RecordType == RecordType.Soa) &&
                                         (name.Equals(x.Name) || name.IsSubDomainOf(x.Name)))
                                  .OfType <SoaRecord>()
                                  .FirstOrDefault();

            if (soaRecord != null)
            {
                _cache.Add(name, recordType, recordClass, new List <DnsRecordBase>(), DnsSecValidationResult.Indeterminate, soaRecord.NegativeCachingTTL);
                return(new List <T>());
            }

            // authoritive response does not contain answer
            throw new Exception("Could not resolve " + name);
        }
        private async Task <DnsMessage> ResolveMessageAsync(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token)
        {
            for (; state.QueryCount <= MaximumReferalCount; state.QueryCount++)
            {
                DnsMessage msg = await new DnsClient(GetBestNameservers(recordType == RecordType.Ds ? name.GetParentName() : name), QueryTimeout)
                {
                    IsResponseValidationEnabled = IsResponseValidationEnabled,
                    Is0x20ValidationEnabled     = Is0x20ValidationEnabled
                }.ResolveAsync(name, recordType, recordClass, new DnsQueryOptions()
                {
                    IsRecursionDesired = false,
                    IsEDnsEnabled      = true
                }, token);

                if ((msg != null) && ((msg.ReturnCode == ReturnCode.NoError) || (msg.ReturnCode == ReturnCode.NxDomain)))
                {
                    if (msg.IsAuthoritiveAnswer)
                    {
                        return(msg);
                    }

                    List <NsRecord> referalRecords = msg.AuthorityRecords
                                                     .Where(x =>
                                                            (x.RecordType == RecordType.Ns) &&
                                                            (name.Equals(x.Name) || name.IsSubDomainOf(x.Name)))
                                                     .OfType <NsRecord>()
                                                     .ToList();

                    if (referalRecords.Count > 0)
                    {
                        if (referalRecords.GroupBy(x => x.Name).Count() == 1)
                        {
                            var newServers = referalRecords.Join(msg.AdditionalRecords.OfType <AddressRecordBase>(), x => x.NameServer, x => x.Name, (x, y) => new { y.Address, TimeToLive = Math.Min(x.TimeToLive, y.TimeToLive) }).ToList();

                            if (newServers.Count > 0)
                            {
                                DomainName zone = referalRecords.First().Name;

                                foreach (var newServer in newServers)
                                {
                                    _nameserverCache.Add(zone, newServer.Address, newServer.TimeToLive);
                                }

                                continue;
                            }
                            else
                            {
                                NsRecord firstReferal = referalRecords.First();

                                var newLookedUpServers = await ResolveHostWithTtlAsync(firstReferal.NameServer, state, token);

                                foreach (var newServer in newLookedUpServers)
                                {
                                    _nameserverCache.Add(firstReferal.Name, newServer.Item1, Math.Min(firstReferal.TimeToLive, newServer.Item2));
                                }

                                if (newLookedUpServers.Count > 0)
                                {
                                    continue;
                                }
                            }
                        }
                    }

                    // Response of best known server is not authoritive and has no referrals --> No chance to get a result
                    throw new Exception("Could not resolve " + name);
                }
            }

            // query limit reached without authoritive answer
            throw new Exception("Could not resolve " + name);
        }
        private async Task <SpfQualifier> CheckMechanismAsync(SpfMechanism mechanism, IPAddress ip, DomainName domain, string sender, State state, CancellationToken token)
        {
            switch (mechanism.Type)
            {
            case SpfMechanismType.All:
                return(mechanism.Qualifier);

            case SpfMechanismType.A:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                DomainName aMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                bool?isAMatch = await IsIpMatchAsync(aMechanismDomain, ip, mechanism.Prefix, mechanism.Prefix6, token);

                if (!isAMatch.HasValue)
                {
                    return(SpfQualifier.TempError);
                }

                if (isAMatch.Value)
                {
                    return(mechanism.Qualifier);
                }
                break;

            case SpfMechanismType.Mx:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                DomainName mxMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                DnsResolveResult <MxRecord> dnsMxResult = await ResolveDnsAsync <MxRecord>(mxMechanismDomain, RecordType.Mx, token);

                if ((dnsMxResult == null) || ((dnsMxResult.ReturnCode != ReturnCode.NoError) && (dnsMxResult.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                int mxCheckedCount = 0;

                foreach (MxRecord mxRecord in dnsMxResult.Records)
                {
                    if (++mxCheckedCount == 10)
                    {
                        break;
                    }

                    bool?isMxMatch = await IsIpMatchAsync(mxRecord.ExchangeDomainName, ip, mechanism.Prefix, mechanism.Prefix6, token);

                    if (!isMxMatch.HasValue)
                    {
                        return(SpfQualifier.TempError);
                    }

                    if (isMxMatch.Value)
                    {
                        return(mechanism.Qualifier);
                    }
                }
                break;

            case SpfMechanismType.Ip4:
            case SpfMechanismType.Ip6:
                IPAddress compareAddress;
                if (IPAddress.TryParse(mechanism.Domain, out compareAddress))
                {
                    if (ip.AddressFamily != compareAddress.AddressFamily)
                    {
                        return(SpfQualifier.None);
                    }

                    if (mechanism.Prefix.HasValue)
                    {
                        if ((mechanism.Prefix.Value < 0) || (mechanism.Prefix.Value > (compareAddress.AddressFamily == AddressFamily.InterNetworkV6 ? 128 : 32)))
                        {
                            return(SpfQualifier.PermError);
                        }

                        if (ip.GetNetworkAddress(mechanism.Prefix.Value).Equals(compareAddress.GetNetworkAddress(mechanism.Prefix.Value)))
                        {
                            return(mechanism.Qualifier);
                        }
                    }
                    else if (ip.Equals(compareAddress))
                    {
                        return(mechanism.Qualifier);
                    }
                }
                else
                {
                    return(SpfQualifier.PermError);
                }

                break;

            case SpfMechanismType.Ptr:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                DnsResolveResult <PtrRecord> dnsPtrResult = await ResolveDnsAsync <PtrRecord>(ip.GetReverseLookupDomain(), RecordType.Ptr, token);

                if ((dnsPtrResult == null) || ((dnsPtrResult.ReturnCode != ReturnCode.NoError) && (dnsPtrResult.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                DomainName ptrMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                int ptrCheckedCount = 0;
                foreach (PtrRecord ptrRecord in dnsPtrResult.Records)
                {
                    if (++ptrCheckedCount == 10)
                    {
                        break;
                    }

                    bool?isPtrMatch = await IsIpMatchAsync(ptrRecord.PointerDomainName, ip, 0, 0, token);

                    if (isPtrMatch.HasValue && isPtrMatch.Value)
                    {
                        if (ptrRecord.PointerDomainName.Equals(ptrMechanismDomain) || (ptrRecord.PointerDomainName.IsSubDomainOf(ptrMechanismDomain)))
                        {
                            return(mechanism.Qualifier);
                        }
                    }
                }
                break;

            case SpfMechanismType.Exist:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                if (String.IsNullOrEmpty(mechanism.Domain))
                {
                    return(SpfQualifier.PermError);
                }

                DomainName existsMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                DnsResolveResult <ARecord> dnsAResult = await ResolveDnsAsync <ARecord>(existsMechanismDomain, RecordType.A, token);

                if ((dnsAResult == null) || ((dnsAResult.ReturnCode != ReturnCode.NoError) && (dnsAResult.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                if (dnsAResult.Records.Count(record => (record.RecordType == RecordType.A)) > 0)
                {
                    return(mechanism.Qualifier);
                }
                break;

            case SpfMechanismType.Include:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                if (String.IsNullOrEmpty(mechanism.Domain))
                {
                    return(SpfQualifier.PermError);
                }

                DomainName includeMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                if (includeMechanismDomain.Equals(domain))
                {
                    return(SpfQualifier.PermError);
                }

                var includeResult = await CheckHostInternalAsync(ip, includeMechanismDomain, sender, false, state, token);

                switch (includeResult.Result)
                {
                case SpfQualifier.Pass:
                    return(mechanism.Qualifier);

                case SpfQualifier.Fail:
                case SpfQualifier.SoftFail:
                case SpfQualifier.Neutral:
                    return(SpfQualifier.None);

                case SpfQualifier.TempError:
                    return(SpfQualifier.TempError);

                case SpfQualifier.PermError:
                case SpfQualifier.None:
                    return(SpfQualifier.PermError);
                }
                break;

            default:
                return(SpfQualifier.PermError);
            }

            return(SpfQualifier.None);
        }
        private async Task <ValidationResult> CheckHostInternalAsync(IPAddress ip, DomainName domain, string sender, bool expandExplanation, State state, CancellationToken token)
        {
            if ((domain == null) || (domain.Equals(DomainName.Root)))
            {
                return(new ValidationResult()
                {
                    Result = SpfQualifier.None, Explanation = String.Empty
                });
            }

            if (String.IsNullOrEmpty(sender))
            {
                sender = "postmaster@unknown";
            }
            else if (!sender.Contains('@'))
            {
                sender = "postmaster@" + sender;
            }

            LoadRecordResult loadResult = await LoadRecordsAsync(domain, token);

            if (!loadResult.CouldBeLoaded)
            {
                return(new ValidationResult()
                {
                    Result = loadResult.ErrorResult, Explanation = String.Empty
                });
            }

            T record = loadResult.Record;

            if ((record.Terms == null) || (record.Terms.Count == 0))
            {
                return new ValidationResult()
                       {
                           Result = SpfQualifier.Neutral, Explanation = String.Empty
                       }
            }
            ;

            if (record.Terms.OfType <SpfModifier>().GroupBy(m => m.Type).Where(g => (g.Key == SpfModifierType.Exp) || (g.Key == SpfModifierType.Redirect)).Any(g => g.Count() > 1))
            {
                return new ValidationResult()
                       {
                           Result = SpfQualifier.PermError, Explanation = String.Empty
                       }
            }
            ;

            ValidationResult result = new ValidationResult()
            {
                Result = loadResult.ErrorResult
            };

            #region Evaluate mechanism
            foreach (SpfMechanism mechanism in record.Terms.OfType <SpfMechanism>())
            {
                if (state.DnsLookupCount > DnsLookupLimit)
                {
                    return new ValidationResult()
                           {
                               Result = SpfQualifier.PermError, Explanation = String.Empty
                           }
                }
                ;

                SpfQualifier qualifier = await CheckMechanismAsync(mechanism, ip, domain, sender, state, token);

                if (qualifier != SpfQualifier.None)
                {
                    result.Result = qualifier;

                    break;
                }
            }
            #endregion

            #region Evaluate modifiers
            if (result.Result == SpfQualifier.None)
            {
                SpfModifier redirectModifier = record.Terms.OfType <SpfModifier>().FirstOrDefault(m => m.Type == SpfModifierType.Redirect);
                if (redirectModifier != null)
                {
                    if (++state.DnsLookupCount > 10)
                    {
                        return new ValidationResult()
                               {
                                   Result = SpfQualifier.PermError, Explanation = String.Empty
                               }
                    }
                    ;

                    DomainName redirectDomain = await ExpandDomainAsync(redirectModifier.Domain ?? String.Empty, ip, domain, sender, token);

                    if ((redirectDomain == null) || (redirectDomain == DomainName.Root) || (redirectDomain.Equals(domain)))
                    {
                        result.Result = SpfQualifier.PermError;
                    }
                    else
                    {
                        result = await CheckHostInternalAsync(ip, redirectDomain, sender, expandExplanation, state, token);

                        if (result.Result == SpfQualifier.None)
                        {
                            result.Result = SpfQualifier.PermError;
                        }
                    }
                }
            }
            else if ((result.Result == SpfQualifier.Fail) && expandExplanation)
            {
                SpfModifier expModifier = record.Terms.OfType <SpfModifier>().FirstOrDefault(m => m.Type == SpfModifierType.Exp);
                if (expModifier != null)
                {
                    DomainName target = await ExpandDomainAsync(expModifier.Domain, ip, domain, sender, token);

                    if ((target == null) || (target.Equals(DomainName.Root)))
                    {
                        result.Explanation = String.Empty;
                    }
                    else
                    {
                        DnsResolveResult <TxtRecord> dnsResult = await ResolveDnsAsync <TxtRecord>(target, RecordType.Txt, token);

                        if ((dnsResult != null) && (dnsResult.ReturnCode == ReturnCode.NoError))
                        {
                            TxtRecord txtRecord = dnsResult.Records.FirstOrDefault();
                            if (txtRecord != null)
                            {
                                result.Explanation = (await ExpandMacroAsync(txtRecord.TextData, ip, domain, sender, token)).ToString();
                            }
                        }
                    }
                }
            }
            #endregion

            if (result.Result == SpfQualifier.None)
            {
                result.Result = SpfQualifier.Neutral;
            }

            return(result);
        }
예제 #17
0
        public void Must_be_equatable_to_String()
        {
            var a = new DomainName("example.com");

            a.Equals("example.com").Should().Be(true);
        }
예제 #18
0
        public void Must_be_equatable_to_Empty()
        {
            var a = new DomainName("example.com");

            a.Equals(DomainName.Empty).Should().Be(false);
        }
예제 #19
0
 public bool Equals(string userName, string domainName, string environmentName)
 {
     return((UserName != null) && UserName.Equals(userName, StringComparison.InvariantCultureIgnoreCase) &&
            (DomainName != null) && DomainName.Equals(domainName, StringComparison.InvariantCultureIgnoreCase) &&
            (EnvironmentName != null) && EnvironmentName.Equals(environmentName, StringComparison.InvariantCultureIgnoreCase));
 }
예제 #20
0
        private async Task <DnsSecResult <T> > ResolveAsyncInternal <T>(DomainName name, RecordType recordType, RecordClass recordClass, State state, CancellationToken token)
            where T : DnsRecordBase
        {
            DnsCacheRecordList <T> cachedResults;

            if (_cache.TryGetRecords(name, recordType, recordClass, out cachedResults))
            {
                return(new DnsSecResult <T>(cachedResults, cachedResults.ValidationResult));
            }

            DnsCacheRecordList <CNameRecord> cachedCNames;

            if (_cache.TryGetRecords(name, RecordType.CName, recordClass, out cachedCNames))
            {
                var cNameResult = await ResolveAsyncInternal <T>(cachedCNames.First().CanonicalName, recordType, recordClass, state, token);

                return(new DnsSecResult <T>(cNameResult.Records, cachedCNames.ValidationResult == cNameResult.ValidationResult ? cachedCNames.ValidationResult : DnsSecValidationResult.Unsigned));
            }

            DnsMessage msg = await ResolveMessageAsync(name, recordType, recordClass, state, token);

            // check for cname
            List <DnsRecordBase> cNameRecords = msg.AnswerRecords.Where(x => (x.RecordType == RecordType.CName) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList();

            if (cNameRecords.Count > 0)
            {
                DnsSecValidationResult cNameValidationResult = await _validator.ValidateAsync(name, RecordType.CName, recordClass, msg, cNameRecords, state, token);

                if ((cNameValidationResult == DnsSecValidationResult.Bogus) || (cNameValidationResult == DnsSecValidationResult.Indeterminate))
                {
                    throw new DnsSecValidationException("CNAME record could not be validated");
                }

                _cache.Add(name, RecordType.CName, recordClass, cNameRecords, cNameValidationResult, cNameRecords.Min(x => x.TimeToLive));

                DomainName canonicalName = ((CNameRecord)cNameRecords.First()).CanonicalName;

                List <DnsRecordBase> matchingAdditionalRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(canonicalName)).ToList();
                if (matchingAdditionalRecords.Count > 0)
                {
                    DnsSecValidationResult matchingValidationResult = await _validator.ValidateAsync(canonicalName, recordType, recordClass, msg, matchingAdditionalRecords, state, token);

                    if ((matchingValidationResult == DnsSecValidationResult.Bogus) || (matchingValidationResult == DnsSecValidationResult.Indeterminate))
                    {
                        throw new DnsSecValidationException("CNAME matching records could not be validated");
                    }

                    DnsSecValidationResult validationResult = cNameValidationResult == matchingValidationResult ? cNameValidationResult : DnsSecValidationResult.Unsigned;
                    _cache.Add(canonicalName, recordType, recordClass, matchingAdditionalRecords, validationResult, matchingAdditionalRecords.Min(x => x.TimeToLive));

                    return(new DnsSecResult <T>(matchingAdditionalRecords.OfType <T>().ToList(), validationResult));
                }

                var cNameResults = await ResolveAsyncInternal <T>(canonicalName, recordType, recordClass, state, token);

                return(new DnsSecResult <T>(cNameResults.Records, cNameValidationResult == cNameResults.ValidationResult ? cNameValidationResult : DnsSecValidationResult.Unsigned));
            }

            // check for "normal" answer
            List <DnsRecordBase> answerRecords = msg.AnswerRecords.Where(x => (x.RecordType == recordType) && (x.RecordClass == recordClass) && x.Name.Equals(name)).ToList();

            if (answerRecords.Count > 0)
            {
                DnsSecValidationResult validationResult = await _validator.ValidateAsync(name, recordType, recordClass, msg, answerRecords, state, token);

                if ((validationResult == DnsSecValidationResult.Bogus) || (validationResult == DnsSecValidationResult.Indeterminate))
                {
                    throw new DnsSecValidationException("Response records could not be validated");
                }

                _cache.Add(name, recordType, recordClass, answerRecords, validationResult, answerRecords.Min(x => x.TimeToLive));
                return(new DnsSecResult <T>(answerRecords.OfType <T>().ToList(), validationResult));
            }

            // check for negative answer
            SoaRecord soaRecord = msg.AuthorityRecords
                                  .Where(x =>
                                         (x.RecordType == RecordType.Soa) &&
                                         (name.Equals(x.Name) || name.IsSubDomainOf(x.Name)))
                                  .OfType <SoaRecord>()
                                  .FirstOrDefault();

            if (soaRecord != null)
            {
                DnsSecValidationResult validationResult = await _validator.ValidateAsync(name, recordType, recordClass, msg, answerRecords, state, token);

                if ((validationResult == DnsSecValidationResult.Bogus) || (validationResult == DnsSecValidationResult.Indeterminate))
                {
                    throw new DnsSecValidationException("Negative answer could not be validated");
                }

                _cache.Add(name, recordType, recordClass, new List <DnsRecordBase>(), validationResult, soaRecord.NegativeCachingTTL);
                return(new DnsSecResult <T>(new List <T>(), validationResult));
            }

            // authoritive response does not contain answer
            throw new Exception("Could not resolve " + name);
        }
예제 #21
0
            public override bool Equals(object obj)
            {
                CacheKey other = obj as CacheKey;

                if (other == null)
                {
                    return(false);
                }

                return((_recordType == other._recordType) && (_recordClass == other._recordClass) && (_name.Equals(other._name)));
            }