/// <summary>Gets the ID string, i.e. a 'normalized' <see cref="String"/> representation.
        /// </summary>
        /// <param name="rawString">The (raw) string.</param>
        /// <param name="ignorCommentCharacter">A value indicating whether all character which comes next to <see cref="IdentifierString.IgnoringStartCharacter"/> will be ignored.</param>
        /// <returns>A 'normalized' representation of <paramref name="rawString"/>, especially without white spaces.
        /// </returns>
        internal static string GetIDString(string rawString, bool ignorCommentCharacter = true)
        {
            var rawStringSpan = MemoryExtensions.AsSpan(rawString);

            if (ignorCommentCharacter == true)
            {
                int splitIndex = rawString.IndexOf(IgnoringStartCharacter);
                if (splitIndex >= 0)
                {
                    rawStringSpan = rawStringSpan.Slice(0, splitIndex);  // 'rawString = rawString.Remove(splitIndex)'
                }
            }
            int k = 0;
            var identifierAsArray = new char[rawStringSpan.Length];

            for (int i = 0; i < rawStringSpan.Length; i++)
            {
                char c = rawStringSpan[i];
                if (Char.IsWhiteSpace(c) == false)
                {
                    identifierAsArray[k] = Char.ToLower(c);
                    k++;
                }
            }
            return(new string(identifierAsArray, startIndex : 0, length : k));
        }
 // Token: 0x06000184 RID: 388 RVA: 0x00004FC8 File Offset: 0x000031C8
 public void GenerateNonce(Span <byte> target)
 {
     if (target.Length != Interop.SodiumNonceSize)
     {
         throw new ArgumentException(string.Format("Invalid nonce buffer size. Target buffer for the nonce needs to have a capacity of {0} bytes.", Interop.SodiumNonceSize), "target");
     }
     this.CSPRNG.GetBytes(this.Buffer);
     MemoryExtensions.AsSpan <byte>(this.Buffer).CopyTo(target);
 }
        public override int GetAttr(ReadOnlySpan <byte> path, ref stat stat, FuseFileInfoRef fiRef, Guid fileGuid)
        {
            try
            {
                path = base.TransformPath(path);

                if (debug)
                {
                    Console.WriteLine($"NeoFS::GetAttr({RawDirs.HR(path)})");
                    fixed(stat *st = &stat)
                    {
                        var lc = LibC.lstat(toBp(path), st);

                        if (lc < 0)
                        {
                            // Windows file explorer hits lot of files that don't exist
                            //Console.WriteLine($"Stat error: {lc} errno={LibC.errno} path={RawDirs.HR(path)}");
                            return(-LibC.errno);
                        }
                    }

                    // Intercept an asset - we must provide the asset's Attr, not the link of the baked file
                    if ((stat.st_mode & LibC.S_IFMT) == LibC.S_IFLNK)
                    {
                        if (debug)
                        {
                            Console.WriteLine($"Link Seen: Stat mode={stat.st_mode}, S_IFMT={LibC.S_IFMT}, link={LibC.S_IFLNK}");
                        }
                        ssize_t retl;
                        var     buffer = new byte[1024];
                        fixed(byte *b = buffer)
                        {
                            retl = LibC.readlink(toBp(path), b, buffer.Length);
                        }

                        // Trying to do something like startswith for bytes that's fast
                        var link = MemoryExtensions.AsSpan(buffer, 0, assetTag.Length);

                        if (debug)
                        {
                            Console.WriteLine($"NeoFS::GetAttr Asset Detected - ({RawDirs.HR(path)}, {RawDirs.HR(link)}");
                        }

                        if (link.SequenceEqual(assetTag))
                        {
                            link = MemoryExtensions.AsSpan(buffer, 0, (int)retl);
                            if (debug)
                            {
                                Console.WriteLine($"Found ASSET {RawDirs.HR(link)}");
                            }

                            base.GetAssetAttr(path, link, ref stat, fileGuid);
                            return(0);
                        }
                    }

                    if (debug)
                    {
                        Console.WriteLine($"Stat Dump: size={stat.st_size}, mode={stat.st_mode}, mtim={stat.st_mtim}");
                    }

                    return(0);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"GetAttr error: {ex.Message} {ex.StackTrace}");
                return(-LibC.ENOENT);
            }
        }
        // File read

        public override int Open(ReadOnlySpan <byte> path, ref FuseFileInfo fi, Guid fileGuid)
        {
            path = base.TransformPath(path);
            if (path.Length < 1)
            {
                return(-LibC.ENOENT);
            }

            if (debug)
            {
                Console.WriteLine($"NeoFS::Open()");
            }

            // Stat the file

            var stat = new stat();

            var lc = LibC.lstat(toBp(path), &stat);

            if (lc < 0)
            {
                return(-LibC.errno);
            }

            string extAssetSha1 = null;

            // Intercept an asset - we must provide the asset's Attr, not the link of the baked file
            if ((stat.st_mode & LibC.S_IFMT) == LibC.S_IFLNK)
            {
                if (debug)
                {
                    Console.WriteLine($"Stat mode={stat.st_mode}, S_IFMT={LibC.S_IFMT}, link={LibC.S_IFLNK}");
                }

                // Get the link

                ssize_t retl;
                var     buffer = new byte[1024];
                fixed(byte *b = buffer)
                {
                    retl = LibC.readlink(toBp(path), b, buffer.Length);
                }

                // Trying to do something like startswith for bytes that's fast
                var link = MemoryExtensions.AsSpan <byte>(buffer, 0, assetTag.Length);

                if (debug)
                {
                    Console.WriteLine($"NeoFS::GetAttr Asset Detected - ({RawDirs.HR(path)}, {RawDirs.HR(link)}");
                }

                if (link.SequenceEqual(assetTag))
                {
                    link = MemoryExtensions.AsSpan <byte>(buffer, 0, (int)retl);
                    if (debug)
                    {
                        Console.WriteLine($"Found ASSET {RawDirs.HR(link)}");
                    }

                    var asset = link.Slice(assetTag.Length);
                    extAssetSha1 = Encoding.ASCII.GetString(asset);
                }
                else
                {
                    link = MemoryExtensions.AsSpan <byte>(buffer, 0, (int)retl);

                    //path = base.TransformPath()   - have to figure out how to pass to our mountmapper
                    // Probably a dependancy injection
                    // These links shouldn't happen, but it would be a nice attack vector
                }
            }

            // See if asset -- if so, set to asset mode and call base

            if (extAssetSha1 != null)  // Asset Mode
            {
                var fakeFd = LibC.open(toBp(fakeFile), 0);
                if (fakeFd > 0)
                {
                    fi.fh = (ulong)fakeFd;
                    FileContexts.Add(fi.fh, new FileContext
                    {
                        AssetLink     = null,
                        ExtAssetSha1  = extAssetSha1,
                        ExtFileHandle = null,
                    });
                    //Console.WriteLine($"Create Context (sha1) ID={fi.fh}");
                }
                else
                {
                    Console.WriteLine($"Error Opening /dev/null?  Error={LibC.errno}");
                }
                return(base.AssetOpen(path, ref fi, fileGuid));
            }

            // transform the link

            var newFd = LibC.open(toBp(path), fi.flags);

            if (newFd > 0)
            {
                fi.fh = (ulong)newFd;

                // Make a context anyway
                FileContexts.Add(fi.fh, new FileContext
                {
                    AssetLink     = null,
                    ExtAssetSha1  = null,
                    ExtFileHandle = null,
                });
                //Console.WriteLine($"Create Context (null) ID={fi.fh}");

                return(0);
            }

            return(-LibC.errno);
        }
Beispiel #5
0
        private bool TryValidatePseudoHeaders()
        {
            // The initial pseudo header validation takes place in Http2Connection.ValidateHeader and StartStream
            // They make sure the right fields are at least present (except for Connect requests) exactly once.

            _httpVersion = Http.HttpVersion.Http2;

            if (!TryValidateMethod())
            {
                return(false);
            }

            if (!TryValidateAuthorityAndHost(out var hostText))
            {
                return(false);
            }

            // CONNECT - :scheme and :path must be excluded
            if (Method == HttpMethod.Connect)
            {
                if (!String.IsNullOrEmpty(RequestHeaders[HeaderNames.Scheme]) || !String.IsNullOrEmpty(RequestHeaders[HeaderNames.Path]))
                {
                    ResetAndAbort(new ConnectionAbortedException(CoreStrings.Http2ErrorConnectMustNotSendSchemeOrPath), Http2ErrorCode.PROTOCOL_ERROR);
                    return(false);
                }

                RawTarget = hostText;

                return(true);
            }

            // :scheme https://tools.ietf.org/html/rfc7540#section-8.1.2.3
            // ":scheme" is not restricted to "http" and "https" schemed URIs.  A
            // proxy or gateway can translate requests for non - HTTP schemes,
            // enabling the use of HTTP to interact with non - HTTP services.

            // - That said, we shouldn't allow arbitrary values or use them to populate Request.Scheme, right?
            // - For now we'll restrict it to http/s and require it match the transport.
            // - We'll need to find some concrete scenarios to warrant unblocking this.
            if (!string.Equals(RequestHeaders[HeaderNames.Scheme], Scheme, StringComparison.OrdinalIgnoreCase))
            {
                ResetAndAbort(new ConnectionAbortedException($@"The request :scheme header '{RequestHeaders[HeaderNames.Scheme]}' does not match the transport scheme '{Scheme}'."), Http2ErrorCode.PROTOCOL_ERROR);
                return(false);
            }

            // :path (and query) - Required
            // Must start with / except may be * for OPTIONS
            var path = RequestHeaders[HeaderNames.Path].ToString();

            RawTarget = path;

            // OPTIONS - https://tools.ietf.org/html/rfc7540#section-8.1.2.3
            // This pseudo-header field MUST NOT be empty for "http" or "https"
            // URIs; "http" or "https" URIs that do not contain a path component
            // MUST include a value of '/'.  The exception to this rule is an
            // OPTIONS request for an "http" or "https" URI that does not include
            // a path component; these MUST include a ":path" pseudo-header field
            // with a value of '*'.
            if (Method == HttpMethod.Options && path.Length == 1 && path[0] == '*')
            {
                // * is stored in RawTarget only since HttpRequest expects Path to be empty or start with a /.
                Path        = string.Empty;
                QueryString = string.Empty;
                return(true);
            }

            // Approximate MaxRequestLineSize by totaling the required pseudo header field lengths.
            var requestLineLength = _methodText.Length + Scheme.Length + hostText.Length + path.Length;

            if (requestLineLength > ServerOptions.Limits.MaxRequestLineSize)
            {
                ResetAndAbort(new ConnectionAbortedException(CoreStrings.BadRequest_RequestLineTooLong), Http2ErrorCode.PROTOCOL_ERROR);
                return(false);
            }

            var queryIndex = path.IndexOf('?');

            QueryString = queryIndex == -1 ? string.Empty : path.Substring(queryIndex);

            var pathSegment = queryIndex == -1 ? MemoryExtensions.AsSpan(path) : MemoryExtensions.AsSpan(path, 0, queryIndex);

            return(TryValidatePath(pathSegment));
        }