Beispiel #1
0
        public Task <IVirtualFileAsync> GetFileAsync(string virtualPath, NameValueCollection queryString)
        {
            RemoteRequestEventArgs request = ParseRequest(virtualPath, queryString);

            if (request == null)
            {
                throw new FileNotFoundException();
            }

            if (request.SignedRequest && c.get("remotereader.allowAllSignedRequests", false))
            {
                request.DenyRequest = false;
            }

            //Check the whitelist
            if (request.DenyRequest && IsWhitelisted(request))
            {
                request.DenyRequest = false;
            }

            //Fire event
            if (AllowRemoteRequest != null)
            {
                AllowRemoteRequest(this, request);
            }

            if (request.DenyRequest)
            {
                throw new ImageProcessingException(403, "The specified remote URL is not permitted.");
            }

            return(Task.FromResult <IVirtualFileAsync>(new RemoteSiteFile(virtualPath, request, this)));
        }
Beispiel #2
0
        private bool IsWhitelisted(RemoteRequestEventArgs request)
        {
            var rr     = c.getNode("remotereader");
            var domain = new Uri(request.RemoteUrl).Host;

            if (rr == null || string.IsNullOrEmpty(domain))
            {
                return(false);
            }

            foreach (Node n in rr.childrenByName("allow"))
            {
                bool onlyWhenSigned = n.Attrs.Get("onlyWhenSigned", false);
                if (onlyWhenSigned && !request.SignedRequest)
                {
                    continue;
                }

                bool   hostMatches = false, regexMatches = false;
                string host = n.Attrs.Get("domain");
                if (!string.IsNullOrEmpty(host))
                {
                    if (host.StartsWith("*.", StringComparison.OrdinalIgnoreCase))
                    {
                        hostMatches = domain.EndsWith(host.Substring(1), StringComparison.OrdinalIgnoreCase);
                    }
                    else
                    {
                        hostMatches = domain.Equals(host, StringComparison.OrdinalIgnoreCase);
                    }

                    if (!hostMatches)
                    {
                        continue;              //If any filter doesn't match, skip rule
                    }
                }

                string regex = n.Attrs.Get("regex");
                if (!string.IsNullOrEmpty(regex))
                {
                    var r = new Regex("^" + regex + "$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Singleline);
                    regexMatches = r.IsMatch(request.RemoteUrl);
                    if (!regexMatches)
                    {
                        continue;               //If any filter doesn't match, skip rule
                    }
                }
                //If all specified filters match, allow the request.
                //This *is* supposed to be || not &&, because we already deal with non-matching filters via 'continue'.
                if (hostMatches || regexMatches)
                {
                    return(true);
                }
            }
            return(false);
        }
Beispiel #3
0
        /// <summary>
        /// Parses the specified path and querystring. Verifies the HMAC signature for querystring specified paths, parses the
        /// human-friendly syntax for that syntax. Verifies the URL is properly formed. Returns an object containing the remote URL,
        /// querystring remainder, and a flag stating whether the request was signed or not. Incorrectly signed requests immediately throw an exception.
        /// </summary>
        /// <param name="virtualPath"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public RemoteRequestEventArgs ParseRequest(string virtualPath, NameValueCollection query)
        {
            query = new NameValueCollection(query);
            if (!IsRemotePath(virtualPath))
            {
                return(null);
            }

            RemoteRequestEventArgs args = new RemoteRequestEventArgs();

            args.SignedRequest = false;
            args.QueryString   = query;

            if (!string.IsNullOrEmpty(query[Base64UrlKey]))
            {
                string data = query[Base64UrlKey];
                string hmac = query[HmacKey];
                query.Remove(Base64UrlKey);
                query.Remove(HmacKey);
                if (String.IsNullOrEmpty(hmac))
                {
                    args.SignedRequest = false;
                    args.DenyRequest   = true;
                }
                else if (SignData(data).Equals(hmac))
                {
                    args.SignedRequest = true;
                }
                else
                {
                    throw new ImageProcessingException("Invalid request! This request was not properly signed, or has been tampered with since transmission.");
                }
                args.RemoteUrl = PathUtils.FromBase64UToString(data);
            }
            else
            {
                args.RemoteUrl = "http://" + ReplaceInLeadingSegment(virtualPath.Substring(remotePrefix.Length).TrimStart('/', '\\'), "_", ".");
                args.RemoteUrl = Uri.EscapeUriString(args.RemoteUrl);
            }
            if (!SkipUriValidation && !Uri.IsWellFormedUriString(args.RemoteUrl, UriKind.Absolute))
            {
                throw new ImageProcessingException("Invalid request! The specified Uri is invalid: " + args.RemoteUrl);
            }
            return(args);
        }
Beispiel #4
0
 public RemoteSiteFile(string virtualPath, RemoteRequestEventArgs request, RemoteReaderPlugin parent)
 {
     this.virtualPath = virtualPath;
     this.request     = request;
     this.parent      = parent;
 }
Beispiel #5
0
 public RemoteSiteFile(string virtualPath, RemoteRequestEventArgs request, RemoteReaderPlugin parent)
 {
     this.virtualPath = virtualPath;
     this.request = request;
     this.parent = parent;
 }
Beispiel #6
0
        private bool IsWhitelisted(RemoteRequestEventArgs request)
        {
            var rr = c.getNode("remotereader");
            var domain = new Uri(request.RemoteUrl).Host;
            if (rr == null || string.IsNullOrEmpty(domain)) return false;

            foreach (Node n in rr.childrenByName("allow")) {
                bool onlyWhenSigned = NameValueCollectionExtensions.Get(n.Attrs, "onlyWhenSigned", false);
                if (onlyWhenSigned && !request.SignedRequest) continue;

                bool hostMatches = false, regexMatches = false;
                string host = n.Attrs.Get("domain");
                if (!string.IsNullOrEmpty(host)) {
                    if (host.StartsWith("*.", StringComparison.OrdinalIgnoreCase))
                        hostMatches = domain.EndsWith(host.Substring(1), StringComparison.OrdinalIgnoreCase);
                    else
                        hostMatches = domain.Equals(host, StringComparison.OrdinalIgnoreCase);

                    if (!hostMatches) continue;//If any filter doesn't match, skip rule
                }

                string regex = n.Attrs.Get("regex");
                if (!string.IsNullOrEmpty(regex)) {
                    var r = new Regex("^" + regex + "$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Singleline);
                    regexMatches = r.IsMatch(request.RemoteUrl);
                    if (!regexMatches) continue;//If any filter doesn't match, skip rule
                }
                //If all specified filters match, allow the request.
                //This *is* supposed to be || not &&, because we already deal with non-matching filters via 'continue'.
                if (hostMatches || regexMatches) return true;

            }
            return false;
        }
Beispiel #7
0
        /// <summary>
        /// Parses the specified path and querystring. Verifies the hmac signature for querystring specified paths, parses the
        /// human-friendly syntax for that syntax. Verifies the URL is properly formed. Returns an object containing the remote URL,
        /// querystring remainder, and a flag stating whether the request was signed or not. Incorrectly signed requests immediately throw an exception.
        /// </summary>
        /// <param name="virtualPath"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public RemoteRequestEventArgs ParseRequest(string virtualPath, NameValueCollection query)
        {
            query = new NameValueCollection(query);
            if (!IsRemotePath(virtualPath)) return null;

            RemoteRequestEventArgs args = new RemoteRequestEventArgs();
            args.SignedRequest = false;
            args.QueryString = query;

            if (!string.IsNullOrEmpty(query[Base64UrlKey])) {
                string data = query[Base64UrlKey];
                string hmac = query[HmacKey];
                query.Remove(Base64UrlKey);
                query.Remove(HmacKey);
                if (String.IsNullOrEmpty(hmac))
                {
                    args.SignedRequest = false;
                    args.DenyRequest = true;
                }
                else if (SignData(data).Equals(hmac))
                {
                    args.SignedRequest = true;
                }
                else
                {
                    throw new ImageProcessingException("Invalid request! This request was not properly signed, or has been tampered with since transmission.");
                }
                args.RemoteUrl = PathUtils.FromBase64UToString(data);
            } else {
                args.RemoteUrl = "http://" + ReplaceInLeadingSegment(virtualPath.Substring(remotePrefix.Length).TrimStart('/', '\\'), "_", ".");
                args.RemoteUrl = Uri.EscapeUriString(args.RemoteUrl);
            }
            if (!Uri.IsWellFormedUriString(args.RemoteUrl, UriKind.Absolute))
                throw new ImageProcessingException("Invalid request! The specified Uri is invalid: " + args.RemoteUrl);
            return args;
        }