예제 #1
0
        /// <summary>
        /// Checks if the mechamism matches the current request.
        /// </summary>
        /// <returns>Match result</returns>
        public override async Task <SpfResult> Matches()
        {
            try
            {
                if (this.term.dnsLookupsLeft-- <= 0)
                {
                    throw new Exception("DNS Lookup maximum reached.");
                }

                string   TargetDomain = this.TargetDomain;
                string[] DomainNames  = await DnsResolver.LookupDomainName(this.term.ip);

                // First check if domain is found.

                foreach (string DomainName in DomainNames)
                {
                    if (string.Compare(DomainName, TargetDomain, true) == 0 &&
                        await this.MatchReverseIp(DomainName))
                    {
                        return(SpfResult.Pass);
                    }
                }

                // Second, check if sub-domain is found.

                foreach (string DomainName in DomainNames)
                {
                    if (DomainName.EndsWith("." + TargetDomain, StringComparison.CurrentCultureIgnoreCase) &&
                        await this.MatchReverseIp(DomainName))
                    {
                        return(SpfResult.Pass);
                    }
                }
            }
            catch (Exception)
            {
                // Fail
            }

            return(SpfResult.Fail);
        }
예제 #2
0
        /// <summary>
        /// Expands any macros in the domain specification.
        /// </summary>
        public override async Task Expand()
        {
            if (this.expanded)
            {
                return;
            }

            this.expanded = true;
            this.term.Reset(this.domain);

            StringBuilder sb = new StringBuilder();
            char          ch;

            while ((ch = this.term.PeekNextChar()) > ' ')
            {
                this.term.pos++;

                if (ch == '%')
                {
                    switch (ch = this.term.PeekNextChar())
                    {
                    case (char)0:
                        sb.Append('%');
                        break;

                    case '%':
                        this.term.pos++;
                        sb.Append('%');
                        break;

                    case '_':
                        this.term.pos++;
                        sb.Append(' ');
                        break;

                    case '-':
                        this.term.pos++;
                        sb.Append("%20");
                        break;

                    case '{':
                        this.term.pos++;

                        char MacroLetter = char.ToLower(this.term.NextChar());
                        int? Digit;
                        bool Reverse;

                        if (char.IsDigit(this.term.PeekNextChar()))
                        {
                            Digit = this.term.NextInteger();

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

                        if (char.ToLower(this.term.PeekNextChar()) == 'r')
                        {
                            this.term.pos++;
                            Reverse = true;
                        }
                        else
                        {
                            Reverse = false;
                        }

                        int Start = this.term.pos;
                        while ((ch = this.term.PeekNextChar()) == '.' || ch == '-' || ch == '+' ||
                               ch == ',' || ch == '/' || ch == '_' || ch == '=')
                        {
                            this.term.pos++;
                        }

                        string Delimiter = this.term.s.Substring(Start, this.term.pos - Start);

                        ch = this.term.NextChar();
                        if (ch != '}')
                        {
                            throw new Exception("Expected }");
                        }

                        string s;

                        switch (MacroLetter)
                        {
                        case 's':                                           // sender
                            s = this.term.sender;
                            break;

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

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

                        case 'd':                                           // domain
                            s = this.term.domain;
                            break;

                        case 'i':
                            switch (this.term.ip.AddressFamily)
                            {
                            case AddressFamily.InterNetwork:
                                s = this.term.ip.ToString();
                                break;

                            case AddressFamily.InterNetworkV6:
                                byte[] Bin = this.term.ip.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 (this.term.dnsLookupsLeft-- <= 0)
                                {
                                    throw new Exception("DNS Lookup maximum reached.");
                                }

                                string[] DomainNames = await DnsResolver.LookupDomainName(this.term.ip);

                                // First check if domain is found.

                                s = null;
                                foreach (string DomainName in DomainNames)
                                {
                                    if (string.Compare(DomainName, this.term.domain, true) == 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("." + this.term.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 (this.term.ip.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 = this.term.helloDomain;
                            break;

                        case 'c':
                            this.AssertExp();
                            s = this.term.ip.ToString();
                            break;

                        case 'r':
                            this.AssertExp();
                            s = this.term.hostDomain;
                            break;

                        case 't':
                            this.AssertExp();
                            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:
                        this.term.pos++;
                        sb.Append('%');
                        sb.Append(ch);
                        break;
                    }
                }
                else
                {
                    sb.Append(ch);
                }
            }

            this.domain = sb.ToString();
        }