コード例 #1
0
 public Ip4(SpfStatement spfStatement, SpfQualifier qualifier) : base(spfStatement, qualifier)
 {
     if (IpAddress.AddressFamily != AddressFamily.InterNetwork)
     {
         throw new Exception("IPv4 address expected.");
     }
 }
コード例 #2
0
ファイル: Ip.cs プロジェクト: large/NetSPF
        public Ip(SpfStatement spfStatement, SpfQualifier qualifier) : base(spfStatement, qualifier)
        {
            if (SpfStatement.PeekNextCharacter() != ':')
            {
                throw new Exception(": expected.");
            }

            SpfStatement.NextCharacter();

            int  start = SpfStatement.Position;
            char ch;

            while (SpfStatement.Position < SpfStatement.Statement.Length &&
                   (ch = SpfStatement.Statement[SpfStatement.Position]) != '/' && ch > ' ')
            {
                SpfStatement.Position++;
            }

            if (!IPAddress.TryParse(SpfStatement.Statement.Substring(start, SpfStatement.Position - start),
                                    out IpAddress))
            {
                throw new Exception("IP Address expected.");
            }

            int max;

            switch (IpAddress.AddressFamily)
            {
            case AddressFamily.InterNetwork:
                max = 32;
                break;

            case AddressFamily.InterNetworkV6:
                max = 128;
                break;

            default:
                throw new Exception("IP Address expected.");
            }

            if (SpfStatement.PeekNextCharacter() == '/')
            {
                SpfStatement.NextCharacter();

                Cidr = SpfStatement.NextInteger();
                if (Cidr < 0 || Cidr > max)
                {
                    throw new Exception("Invalid CIDR");
                }
            }
            else
            {
                Cidr = max;
            }
        }
コード例 #3
0
        internal static bool Matches(IPAddress[] addresses, SpfStatement statement, int cidr)
        {
            byte[] statementAddressBytes = statement.IpAddress.GetAddressBytes();
            int    c = statementAddressBytes.Length;

            foreach (IPAddress addr in addresses)
            {
                byte[] addressBytes = addr.GetAddressBytes();
                if (addressBytes.Length != c)
                {
                    continue;
                }

                int bitsLeft = cidr;
                int pos      = 0;

                while (bitsLeft > 0 && pos < c)
                {
                    if (bitsLeft >= 8)
                    {
                        if (statementAddressBytes[pos] != addressBytes[pos])
                        {
                            break;
                        }

                        bitsLeft -= 8;
                    }
                    else
                    {
                        byte mask = (byte)(0xff << (8 - bitsLeft));

                        if ((statementAddressBytes[pos] & mask) != (addressBytes[pos] & mask))
                        {
                            break;
                        }

                        bitsLeft = 0;
                    }

                    pos++;
                }

                if (bitsLeft == 0)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #4
0
        public DomainCidrSpecification(SpfStatement statement, SpfQualifier spfQualifier)
            : base(statement, spfQualifier)
        {
            if (statement.PeekNextCharacter() == '/')
            {
                statement.NextCharacter();
                bool hasIpv4;

                if (hasIpv4 = char.IsDigit(statement.PeekNextCharacter()))
                {
                    Ipv4Cidr = statement.NextInteger();
                    if (Ipv4Cidr < 0 || Ipv4Cidr > 32)
                    {
                        throw new Exception("Invalid IPv4 CIDR");
                    }
                }

                if (statement.PeekNextCharacter() == '/')
                {
                    statement.NextCharacter();

                    if (hasIpv4 && statement.PeekNextCharacter() == '/')
                    {
                        statement.NextCharacter();
                    }

                    if (char.IsDigit(statement.PeekNextCharacter()))
                    {
                        Ipv6Cidr = statement.NextInteger();
                        if (Ipv6Cidr < 0 || Ipv6Cidr > 128)
                        {
                            throw new Exception("Invalid IPv6 CIDR");
                        }
                    }
                    else if (!hasIpv4)
                    {
                        throw new Exception("IPv4 or IPv6 CIDR expected.");
                    }
                }
            }
        }
コード例 #5
0
ファイル: DomainSpecification.cs プロジェクト: large/NetSPF
        public DomainSpecification(SpfStatement spfStatement, SpfQualifier qualifier) : base(spfStatement, qualifier)
        {
            if (SpfStatement.PeekNextCharacter() == Separator)
            {
                SpfStatement.NextCharacter();

                var  start = SpfStatement.Position;
                char ch;

                while ((ch = SpfStatement.PeekNextCharacter()) > ' ' && ch != '/')
                {
                    SpfStatement.Position++;
                }

                Domain = SpfStatement.Statement.Substring(start, SpfStatement.Position - start);
            }
            else if (DomainRequired)
            {
                throw new Exception($"{Separator} expected");
            }
        }
コード例 #6
0
ファイル: A.cs プロジェクト: large/NetSPF
        internal static async Task <bool> Matches(string domain, SpfStatement statement, int cidr4, int cidr6)
        {
            IPAddress[] addresses;

            int cidr;

            switch (statement.IpAddress.AddressFamily)
            {
            case AddressFamily.InterNetwork:
                if (statement.RemainingQueries-- <= 0)
                {
                    throw new Exception("DNS Lookup maximum reached.");
                }

                addresses = await DnsResolver.LookupIp4Addresses(domain);

                cidr = cidr4;
                break;

            case AddressFamily.InterNetworkV6:
                if (statement.RemainingQueries-- <= 0)
                {
                    throw new Exception("DNS Lookup maximum reached.");
                }

                addresses = await DnsResolver.LookupIp6Addresses(domain);

                cidr = cidr6;
                break;

            default:
                return(false);
            }

            return(Matches(addresses, statement, cidr));
        }
コード例 #7
0
ファイル: Explanation.cs プロジェクト: large/NetSPF
        public async Task <string> Evaluate()
        {
            try
            {
                await Expand();

                StringBuilder sb = new StringBuilder();

                foreach (string text in await DnsResolver.LookupText(Domain))
                {
                    sb.Append(text); // No white-space delimiter
                }
                SpfStatement.Reset("=" + sb.ToString());
                Explanation explanation = new Explanation(SpfStatement, Qualifier);

                await explanation.Expand();

                return(explanation.Domain);
            }
            catch (Exception)
            {
                return(null);
            }
        }
コード例 #8
0
ファイル: DomainSpecification.cs プロジェクト: large/NetSPF
        public override async Task Expand()
        {
            if (_expanded)
            {
                return;
            }

            _expanded = true;
            SpfStatement.Reset(Domain);

            StringBuilder sb = new StringBuilder();
            char          ch;

            while ((ch = SpfStatement.PeekNextCharacter()) > ' ')
            {
                SpfStatement.Position++;

                if (ch == '%')
                {
                    switch (ch = SpfStatement.PeekNextCharacter())
                    {
                    case (char)0:
                        sb.Append('%');
                        break;

                    case '%':
                        SpfStatement.Position++;
                        sb.Append('%');
                        break;

                    case '_':
                        SpfStatement.Position++;
                        sb.Append(' ');
                        break;

                    case '-':
                        SpfStatement.Position++;
                        sb.Append("%20");
                        break;

                    case '{':
                        SpfStatement.Position++;

                        char macroLetter = char.ToLower(SpfStatement.NextCharacter());
                        int? digit;
                        bool reverse;

                        if (char.IsDigit(SpfStatement.PeekNextCharacter()))
                        {
                            digit = SpfStatement.NextInteger();

                            if (digit == 0)
                            {
                                throw new Exception("Invalid number of digits.");
                            }
                        }
                        else
                        {
                            digit = null;
                        }

                        if (char.ToLower(SpfStatement.PeekNextCharacter()) == 'r')
                        {
                            SpfStatement.Position++;
                            reverse = true;
                        }
                        else
                        {
                            reverse = false;
                        }

                        int start = SpfStatement.Position;
                        while ((ch = SpfStatement.PeekNextCharacter()) == '.' || ch == '-' || ch == '+' ||
                               ch == ',' || ch == '/' || ch == '_' || ch == '=')
                        {
                            SpfStatement.Position++;
                        }

                        string delimiter =
                            SpfStatement.Statement.Substring(start, SpfStatement.Position - start);

                        ch = SpfStatement.NextCharacter();
                        if (ch != '}')
                        {
                            throw new Exception("Expected }");
                        }

                        string s;

                        switch (macroLetter)
                        {
                        case 's':         // sender
                            s = SpfStatement.Sender;
                            break;

                        case 'l':         // local-part of sender
                            s = SpfStatement.Sender;
                            int i = s.IndexOf('@');
                            if (i < 0)
                            {
                                s = string.Empty;
                            }
                            else
                            {
                                s = s.Substring(0, i);
                            }
                            break;

                        case 'o':         // domain of sender
                            s = SpfStatement.Sender;
                            i = s.IndexOf('@');
                            if (i >= 0)
                            {
                                s = s.Substring(i + 1);
                            }
                            break;

                        case 'd':         // domain
                            s = SpfStatement.Domain;
                            break;

                        case 'i':
                            switch (SpfStatement.IpAddress.AddressFamily)
                            {
                            case AddressFamily.InterNetwork:
                                s = SpfStatement.IpAddress.ToString();
                                break;

                            case AddressFamily.InterNetworkV6:
                                byte[] bin = SpfStatement.IpAddress.GetAddressBytes();

                                StringBuilder sb2 = new StringBuilder();
                                byte          b, b2;

                                for (i = 0; i < 16; i++)
                                {
                                    b = bin[i];

                                    b2 = (byte)(b >> 4);
                                    if (b2 < 10)
                                    {
                                        sb2.Append((char)('0' + b2));
                                    }
                                    else
                                    {
                                        sb2.Append((char)('a' + b2 - 10));
                                    }

                                    sb2.Append('.');

                                    b2 = (byte)(b & 15);
                                    if (b2 < 10)
                                    {
                                        sb2.Append((char)('0' + b2));
                                    }
                                    else
                                    {
                                        sb2.Append((char)('a' + b2 - 10));
                                    }

                                    if (i < 15)
                                    {
                                        sb2.Append('.');
                                    }
                                }

                                s = sb2.ToString();
                                break;

                            default:
                                throw new Exception("Invalid client address.");
                            }

                            break;

                        case 'p':
                            try
                            {
                                if (SpfStatement.RemainingQueries-- <= 0)
                                {
                                    throw new Exception("DNS Lookup maximum reached.");
                                }

                                string[] domainNames =
                                    await DnsResolver.LookupDomainName(SpfStatement.IpAddress);

                                // First check if domain is found.

                                s = null;
                                foreach (string domainName in domainNames)
                                {
                                    if (String.Compare(domainName, SpfStatement.Domain,
                                                       StringComparison.OrdinalIgnoreCase) == 0 &&
                                        await this.MatchReverseIp(domainName))
                                    {
                                        s = domainName;
                                        break;
                                    }
                                }

                                if (s is null)
                                {
                                    // Second, check if sub-domain is found.

                                    foreach (string domainName in domainNames)
                                    {
                                        if (domainName.EndsWith("." + SpfStatement.Domain,
                                                                StringComparison.CurrentCultureIgnoreCase) &&
                                            await this.MatchReverseIp(domainName))
                                        {
                                            s = domainName;
                                            break;
                                        }
                                    }

                                    if (s is null)
                                    {
                                        if (domainNames.Length == 0)
                                        {
                                            s = "unknown";
                                        }
                                        else
                                        {
                                            s = domainNames[DnsResolver.Next(domainNames.Length)];
                                        }
                                    }
                                }
                            }
                            catch (ArgumentException)
                            {
                                s = "unknown";
                            }
                            catch (TimeoutException)
                            {
                                s = "unknown";
                            }

                            break;

                        case 'v':
                            switch (SpfStatement.IpAddress.AddressFamily)
                            {
                            case AddressFamily.InterNetwork:
                                s = "in-addr";
                                break;

                            case AddressFamily.InterNetworkV6:
                                s = "ip6";
                                break;

                            default:
                                throw new Exception("Invalid client address.");
                            }

                            break;

                        case 'h':
                            s = SpfStatement.HeloDomain;
                            break;

                        case 'c':
                            this.AssertExplanation();
                            s = SpfStatement.IpAddress.ToString();
                            break;

                        case 'r':
                            this.AssertExplanation();
                            s = SpfStatement.HostDomain;
                            break;

                        case 't':
                            this.AssertExplanation();
                            int seconds = (int)Math.Round((DateTime.UtcNow - UnixEpoch).TotalSeconds);
                            s = seconds.ToString();
                            break;

                        default:
                            throw new Exception("Unknown macro.");
                        }

                        if (reverse || digit.HasValue || !string.IsNullOrEmpty(delimiter))
                        {
                            if (string.IsNullOrEmpty(delimiter))
                            {
                                delimiter = ".";
                            }

                            string[] parts = s.Split(new string[] { delimiter }, StringSplitOptions.None);
                            int      i     = parts.Length;

                            if (reverse)
                            {
                                Array.Reverse(parts);
                            }

                            if (digit.HasValue && digit.Value < i)
                            {
                                i = digit.Value;
                            }

                            bool first = true;
                            int  j     = parts.Length - i;

                            while (i-- > 0)
                            {
                                if (first)
                                {
                                    first = false;
                                }
                                else
                                {
                                    sb.Append('.');
                                }

                                sb.Append(parts[j++]);
                            }
                        }
                        else
                        {
                            sb.Append(s);
                        }

                        break;

                    default:
                        SpfStatement.Position++;
                        sb.Append('%');
                        sb.Append(ch);
                        break;
                    }
                }
                else
                {
                    sb.Append(ch);
                }
            }

            Domain = sb.ToString();
        }
コード例 #9
0
ファイル: Redirect.cs プロジェクト: large/NetSPF
 public Redirect(SpfStatement spfStatement, SpfQualifier qualifier) : base(spfStatement, qualifier)
 {
 }
コード例 #10
0
 public Ptr(SpfStatement spfStatement, SpfQualifier qualifier) : base(spfStatement, qualifier)
 {
 }
コード例 #11
0
 public Exists(SpfStatement spfStatement, SpfQualifier qualifier) : base(spfStatement, qualifier)
 {
 }
コード例 #12
0
ファイル: A.cs プロジェクト: large/NetSPF
 public A(SpfStatement statement, SpfQualifier spfQualifier) : base(statement, spfQualifier)
 {
 }
コード例 #13
0
 public Mechanism(SpfStatement spfStatement, SpfQualifier qualifier)
 {
     Qualifier    = qualifier;
     SpfStatement = spfStatement;
 }
コード例 #14
0
ファイル: Include.cs プロジェクト: large/NetSPF
 public Include(SpfStatement spfStatement, SpfQualifier qualifier, params SpfExpression[] spfExpressions)
     : base(spfStatement, qualifier)
 {
     _spfExpressions = spfExpressions;
 }
コード例 #15
0
ファイル: Explanation.cs プロジェクト: large/NetSPF
 public Explanation(SpfStatement spfStatement, SpfQualifier qualifier) : base(spfStatement, qualifier)
 {
 }