Beispiel #1
0
        /// <summary>
        /// Validates a URL against this trust root.
        /// </summary>
        /// <param name="url">The URL to check.</param>
        /// <returns>Whether the given URL is within this trust root.</returns>
        internal bool Contains(Uri url)
        {
            if (url.Scheme != Scheme)
            {
                return(false);
            }

            if (url.Port != Port)
            {
                return(false);
            }

            if (!DomainWildcard)
            {
                if (url.Host != Host)
                {
                    return(false);
                }
            }
            else
            {
                Debug.Assert(!string.IsNullOrEmpty(Host), "The host part of the Regex should evaluate to at least one char for successful parsed trust roots.");
                string[] host_parts = Host.Split('.');
                string[] url_parts  = url.Host.Split('.');

                // If the domain containing the wildcard has more parts than the URL to match against,
                // it naturally can't be valid.
                // Unless *.example.com actually matches example.com too.
                if (host_parts.Length > url_parts.Length)
                {
                    return(false);
                }

                // Compare last part first and move forward.
                // Maybe could be done by using EndsWith, but piecewies helps ensure that
                // *.my.com doesn't match ohmeohmy.com but can still match my.com.
                for (int i = 0; i < host_parts.Length; i++)
                {
                    string hostPart = host_parts[host_parts.Length - 1 - i];
                    string urlPart  = url_parts[url_parts.Length - 1 - i];
                    if (!string.Equals(hostPart, urlPart, StringComparison.OrdinalIgnoreCase))
                    {
                        return(false);
                    }
                }
            }

            // If path matches or is specified to root ...
            // (deliberately case sensitive to protect security on case sensitive systems)
            if (PathAndQuery.Equals(url.PathAndQuery, StringComparison.Ordinal) ||
                PathAndQuery.Equals("/", StringComparison.Ordinal))
            {
                return(true);
            }

            // If trust root has a longer path, the return URL must be invalid.
            if (PathAndQuery.Length > url.PathAndQuery.Length)
            {
                return(false);
            }

            // The following code assures that http://example.com/directory isn't below http://example.com/dir,
            // but makes sure http://example.com/dir/ectory is below http://example.com/dir
            int    path_len   = PathAndQuery.Length;
            string url_prefix = url.PathAndQuery.Substring(0, path_len);

            if (PathAndQuery != url_prefix)
            {
                return(false);
            }

            // If trust root includes a query string ...
            if (PathAndQuery.Contains("?"))
            {
                // ... make sure return URL begins with a new argument
                return(url.PathAndQuery[path_len] == '&');
            }

            // Or make sure a query string is introduced or a path below trust root
            return(PathAndQuery.EndsWith("/", StringComparison.Ordinal) ||
                   url.PathAndQuery[path_len] == '?' ||
                   url.PathAndQuery[path_len] == '/');
        }